diff --git a/.gitignore b/.gitignore index 65c89d2991..1ebe369c09 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk **/target/ -**/*.db \ No newline at end of file +**/*.db +.idea/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 73f69e0958..0000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/appflowy_client.iml b/.idea/appflowy_client.iml deleted file mode 100644 index f33c861988..0000000000 --- a/.idea/appflowy_client.iml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index e29848431e..0000000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml deleted file mode 100644 index c1ba66c5f7..0000000000 --- a/.idea/libraries/Dart_Packages.xml +++ /dev/null @@ -1,1056 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml deleted file mode 100644 index 6068110626..0000000000 --- a/.idea/libraries/Dart_SDK.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index facec90f25..0000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f4c..0000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift b/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift index dc3b203eab..f0757e328c 100644 --- a/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,6 +6,7 @@ import FlutterMacOS import Foundation import flowy_editor +import flowy_infra_ui import flowy_sdk import path_provider_macos import url_launcher_macos @@ -13,6 +14,7 @@ import window_size func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlowyEditorPlugin.register(with: registry.registrar(forPlugin: "FlowyEditorPlugin")) + FlowyInfraUIPlugin.register(with: registry.registrar(forPlugin: "FlowyInfraUIPlugin")) FlowySdkPlugin.register(with: registry.registrar(forPlugin: "FlowySdkPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/app_flowy/macos/Podfile.lock b/app_flowy/macos/Podfile.lock index 8aca69f25a..54e66df1b4 100644 --- a/app_flowy/macos/Podfile.lock +++ b/app_flowy/macos/Podfile.lock @@ -1,6 +1,8 @@ PODS: - flowy_editor (0.0.1): - FlutterMacOS + - flowy_infra_ui (0.0.1): + - FlutterMacOS - flowy_sdk (0.0.1): - FlutterMacOS - FlutterMacOS (1.0.0) @@ -13,6 +15,7 @@ PODS: DEPENDENCIES: - flowy_editor (from `Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos`) + - flowy_infra_ui (from `Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos`) - flowy_sdk (from `Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) @@ -22,6 +25,8 @@ DEPENDENCIES: EXTERNAL SOURCES: flowy_editor: :path: Flutter/ephemeral/.symlinks/plugins/flowy_editor/macos + flowy_infra_ui: + :path: Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos flowy_sdk: :path: Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos FlutterMacOS: @@ -35,6 +40,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: flowy_editor: 26060a984848e6afac1f6a4455511f4114119d8d + flowy_infra_ui: 9d5021b1610fe0476eb1191bf7cd41c4a4138d8f flowy_sdk: c302ac0a22dea596db0df8073b9637b2bf2ff6fd FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b diff --git a/app_flowy/packages/flowy_infra_ui/.gitignore b/app_flowy/packages/flowy_infra_ui/.gitignore index a247422ef7..e9dc58d3d6 100644 --- a/app_flowy/packages/flowy_infra_ui/.gitignore +++ b/app_flowy/packages/flowy_infra_ui/.gitignore @@ -1,75 +1,7 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp .DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ .dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies + .packages -.pub-cache/ .pub/ + build/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Flutter.podspec -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/ephemeral -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 diff --git a/app_flowy/packages/flowy_infra_ui/.metadata b/app_flowy/packages/flowy_infra_ui/.metadata index f323c72cb1..505610f134 100644 --- a/app_flowy/packages/flowy_infra_ui/.metadata +++ b/app_flowy/packages/flowy_infra_ui/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: 96bbcd006fafade4ad7a4abde77cec32df6846ea + revision: fa5883b78e566877613ad1ccb48dd92075cb5c23 channel: dev -project_type: package +project_type: plugin diff --git a/app_flowy/packages/flowy_infra_ui/.vscode/launch.json b/app_flowy/packages/flowy_infra_ui/.vscode/launch.json new file mode 100644 index 0000000000..ba345105b4 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Infra UI Example", + "type": "dart", + "request": "launch", + "program": "example/lib/main.dart" + }, + ] +} \ No newline at end of file diff --git a/app_flowy/packages/flowy_infra_ui/README.md b/app_flowy/packages/flowy_infra_ui/README.md index 8b55e735b5..2644e9ffa9 100644 --- a/app_flowy/packages/flowy_infra_ui/README.md +++ b/app_flowy/packages/flowy_infra_ui/README.md @@ -1,39 +1,15 @@ - +## Getting Started -TODO: Put a short description of the package here that helps potential users -know whether this package might be useful for them. +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/developing-packages/), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. -## Features +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. -TODO: List what your package can do. Maybe include images, gifs, or videos. - -## Getting started - -TODO: List prerequisites and provide or point to information on how to -start using the package. - -## Usage - -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. - -```dart -const like = 'sample'; -``` - -## Additional information - -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. diff --git a/app_flowy/packages/flowy_infra_ui/android/.classpath b/app_flowy/packages/flowy_infra_ui/android/.classpath new file mode 100644 index 0000000000..4a04201ca2 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/app_flowy/packages/flowy_infra_ui/android/.gitignore b/app_flowy/packages/flowy_infra_ui/android/.gitignore new file mode 100644 index 0000000000..c6cbe562a4 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/app_flowy/packages/flowy_infra_ui/android/.project b/app_flowy/packages/flowy_infra_ui/android/.project new file mode 100644 index 0000000000..77aded223a --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/.project @@ -0,0 +1,34 @@ + + + flowy_infra_ui + Project flowy_infra_ui created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + + + 1626576261667 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/app_flowy/packages/flowy_infra_ui/android/.settings/org.eclipse.buildship.core.prefs b/app_flowy/packages/flowy_infra_ui/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000000..e8895216fd --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/app_flowy/packages/flowy_infra_ui/android/build.gradle b/app_flowy/packages/flowy_infra_ui/android/build.gradle new file mode 100644 index 0000000000..76e9272bbf --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/build.gradle @@ -0,0 +1,34 @@ +group 'com.example.flowy_infra_ui' +version '1.0' + +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 30 + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + dependencies { + implementation "androidx.core:core:1.5.0-rc01" + } +} diff --git a/app_flowy/packages/flowy_infra_ui/android/gradle.properties b/app_flowy/packages/flowy_infra_ui/android/gradle.properties new file mode 100644 index 0000000000..94adc3a3f9 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/app_flowy/packages/flowy_infra_ui/android/gradle/wrapper/gradle-wrapper.properties b/app_flowy/packages/flowy_infra_ui/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..3c9d0852bf --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/app_flowy/packages/flowy_infra_ui/android/settings.gradle b/app_flowy/packages/flowy_infra_ui/android/settings.gradle new file mode 100644 index 0000000000..0dc790b56b --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'flowy_infra_ui' diff --git a/app_flowy/packages/flowy_infra_ui/android/src/main/AndroidManifest.xml b/app_flowy/packages/flowy_infra_ui/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..f93233246e --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/app_flowy/packages/flowy_infra_ui/android/src/main/java/com/example/flowy_infra_ui/FlowyInfraUiPlugin.java b/app_flowy/packages/flowy_infra_ui/android/src/main/java/com/example/flowy_infra_ui/FlowyInfraUiPlugin.java new file mode 100644 index 0000000000..e93c990e62 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/src/main/java/com/example/flowy_infra_ui/FlowyInfraUiPlugin.java @@ -0,0 +1,81 @@ +package com.example.flowy_infra_ui; + +import android.app.Activity; + +import androidx.annotation.NonNull; + +import com.example.flowy_infra_ui.event.KeyboardEventHandler; + +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.embedding.engine.plugins.activity.ActivityAware; +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; +import io.flutter.plugin.common.EventChannel; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; + +/** FlowyInfraUIPlugin */ +public class FlowyInfraUIPlugin implements FlutterPlugin, ActivityAware, MethodCallHandler { + + // MARK: - Constant + public static final String INFRA_UI_METHOD_CHANNEL_NAME = "flowy_infra_ui_method"; + public static final String INFRA_UI_KEYBOARD_EVENT_CHANNEL_NAME = "flowy_infra_ui_event/keyboard"; + + public static final String INFRA_UI_METHOD_GET_PLATFORM_VERSION = "getPlatformVersion"; + + // Method Channel + private MethodChannel methodChannel; + // Event Channel + private KeyboardEventHandler keyboardEventHandler = new KeyboardEventHandler(); + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { + methodChannel = new MethodChannel( + flutterPluginBinding.getBinaryMessenger(), + INFRA_UI_METHOD_CHANNEL_NAME); + methodChannel.setMethodCallHandler(this); + + final EventChannel keyboardEventChannel = new EventChannel( + flutterPluginBinding.getBinaryMessenger(), + INFRA_UI_KEYBOARD_EVENT_CHANNEL_NAME); + keyboardEventChannel.setStreamHandler(keyboardEventHandler); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + methodChannel.setMethodCallHandler(null); + keyboardEventHandler.cancelObserveKeyboardAction(); + } + + @Override + public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { + keyboardEventHandler.observeKeyboardAction(binding.getActivity()); + } + + @Override + public void onDetachedFromActivityForConfigChanges() { + keyboardEventHandler.cancelObserveKeyboardAction(); + } + + @Override + public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { + keyboardEventHandler.observeKeyboardAction(binding.getActivity()); + } + + @Override + public void onDetachedFromActivity() { + keyboardEventHandler.cancelObserveKeyboardAction(); + } + + // MARK: - Method Channel + + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { + if (call.method.equals(INFRA_UI_METHOD_GET_PLATFORM_VERSION)) { + result.success("Android " + android.os.Build.VERSION.RELEASE); + } else { + result.notImplemented(); + } + } +} diff --git a/app_flowy/packages/flowy_infra_ui/android/src/main/java/com/example/flowy_infra_ui/event/KeyboardEventHandler.java b/app_flowy/packages/flowy_infra_ui/android/src/main/java/com/example/flowy_infra_ui/event/KeyboardEventHandler.java new file mode 100644 index 0000000000..6462aa6a93 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/src/main/java/com/example/flowy_infra_ui/event/KeyboardEventHandler.java @@ -0,0 +1,53 @@ +package com.example.flowy_infra_ui.event; + +import android.app.Activity; +import android.os.Build; +import android.view.View; + +import androidx.annotation.RequiresApi; +import androidx.core.view.OnApplyWindowInsetsListener; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import io.flutter.plugin.common.EventChannel; + +public class KeyboardEventHandler implements EventChannel.StreamHandler { + private EventChannel.EventSink eventSink; + private View rootView; + private boolean isKeyboardShow = false; + + @Override + public void onListen(Object arguments, EventChannel.EventSink events) { + eventSink = events; + } + + @Override + public void onCancel(Object arguments) { + eventSink = null; + } + + // MARK: - Helper + + @RequiresApi(Build.VERSION_CODES.R) + public void observeKeyboardAction(Activity activity) { + rootView = activity.findViewById(android.R.id.content); + + ViewCompat.setOnApplyWindowInsetsListener(rootView, new OnApplyWindowInsetsListener() { + @Override + public WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) { + isKeyboardShow = insets.isVisible(WindowInsetsCompat.Type.ime()); + if (eventSink != null) { + eventSink.success(isKeyboardShow); + } + return insets; + } + }); + } + + public void cancelObserveKeyboardAction() { + if (rootView != null) { + ViewCompat.setOnApplyWindowInsetsListener(rootView, null); + rootView = null; + } + } +} diff --git a/app_flowy/packages/flowy_infra_ui/android/src/main/kotlin/com/example/flowy_infra_ui/FlowyInfraUiPlugin.kt b/app_flowy/packages/flowy_infra_ui/android/src/main/kotlin/com/example/flowy_infra_ui/FlowyInfraUiPlugin.kt new file mode 100644 index 0000000000..5d98dd8f10 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/android/src/main/kotlin/com/example/flowy_infra_ui/FlowyInfraUiPlugin.kt @@ -0,0 +1,35 @@ +package com.example.flowy_infra_ui + +import androidx.annotation.NonNull + +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.MethodChannel.Result + +/** FlowyInfraUiPlugin */ +class FlowyInfraUiPlugin: FlutterPlugin, MethodCallHandler { + /// The MethodChannel that will the communication between Flutter and native Android + /// + /// This local reference serves to register the plugin with the Flutter Engine and unregister it + /// when the Flutter Engine is detached from the Activity + private lateinit var channel : MethodChannel + + override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + channel = MethodChannel(flutterPluginBinding.binaryMessenger, "flowy_infra_ui") + channel.setMethodCallHandler(this) + } + + override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { + if (call.method == "getPlatformVersion") { + result.success("Android ${android.os.Build.VERSION.RELEASE}") + } else { + result.notImplemented() + } + } + + override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { + channel.setMethodCallHandler(null) + } +} diff --git a/app_flowy/packages/flowy_infra_ui/example/README.md b/app_flowy/packages/flowy_infra_ui/example/README.md index a135626028..7bc0ab05f6 100644 --- a/app_flowy/packages/flowy_infra_ui/example/README.md +++ b/app_flowy/packages/flowy_infra_ui/example/README.md @@ -1,6 +1,6 @@ -# example +# flowy_infra_ui_example -A new Flutter project. +Demonstrates how to use the flowy_infra_ui plugin. ## Getting Started diff --git a/app_flowy/packages/flowy_infra_ui/example/android/.project b/app_flowy/packages/flowy_infra_ui/example/android/.project new file mode 100644 index 0000000000..b06fea48c8 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/android/.project @@ -0,0 +1,28 @@ + + + android + Project android created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + + + 1626576261654 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/app_flowy/packages/flowy_infra_ui/example/android/.settings/org.eclipse.buildship.core.prefs b/app_flowy/packages/flowy_infra_ui/example/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000000..25e4212285 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) +connection.project.dir= +eclipse.preferences.version=1 +gradle.user.home= +java.home=/Library/Java/JavaVirtualMachines/jdk11.0.5-zulu.jdk/Contents/Home +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/app_flowy/packages/flowy_infra_ui/example/android/app/.classpath b/app_flowy/packages/flowy_infra_ui/example/android/app/.classpath new file mode 100644 index 0000000000..4a04201ca2 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/android/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/app_flowy/packages/flowy_infra_ui/example/android/app/.project b/app_flowy/packages/flowy_infra_ui/example/android/app/.project new file mode 100644 index 0000000000..df522843d5 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/android/app/.project @@ -0,0 +1,34 @@ + + + app + Project app created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + + + 1626576261660 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/app_flowy/packages/flowy_infra_ui/example/android/app/.settings/org.eclipse.buildship.core.prefs b/app_flowy/packages/flowy_infra_ui/example/android/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000000..b1886adb46 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/android/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/app_flowy/packages/flowy_infra_ui/example/android/app/build.gradle b/app_flowy/packages/flowy_infra_ui/example/android/app/build.gradle index 56bfa9b78f..7356196bc3 100644 --- a/app_flowy/packages/flowy_infra_ui/example/android/app/build.gradle +++ b/app_flowy/packages/flowy_infra_ui/example/android/app/build.gradle @@ -26,7 +26,6 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -43,7 +42,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.example" + applicationId "com.example.flowy_infra_ui_example" minSdkVersion 16 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() @@ -57,6 +56,7 @@ android { signingConfig signingConfigs.debug } } + compileSdkVersion 30 } flutter { diff --git a/app_flowy/packages/flowy_infra_ui/example/android/app/src/debug/AndroidManifest.xml b/app_flowy/packages/flowy_infra_ui/example/android/app/src/debug/AndroidManifest.xml index c208884f30..26ef01e2ad 100644 --- a/app_flowy/packages/flowy_infra_ui/example/android/app/src/debug/AndroidManifest.xml +++ b/app_flowy/packages/flowy_infra_ui/example/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.example.flowy_infra_ui_example"> diff --git a/app_flowy/packages/flowy_infra_ui/example/android/app/src/main/AndroidManifest.xml b/app_flowy/packages/flowy_infra_ui/example/android/app/src/main/AndroidManifest.xml index 34dd77efb2..48bd1e58f9 100644 --- a/app_flowy/packages/flowy_infra_ui/example/android/app/src/main/AndroidManifest.xml +++ b/app_flowy/packages/flowy_infra_ui/example/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + package="com.example.flowy_infra_ui_example"> + package="com.example.flowy_infra_ui_example"> diff --git a/app_flowy/packages/flowy_infra_ui/example/android/build.gradle b/app_flowy/packages/flowy_infra_ui/example/android/build.gradle index ed45c65885..3dd86e4db3 100644 --- a/app_flowy/packages/flowy_infra_ui/example/android/build.gradle +++ b/app_flowy/packages/flowy_infra_ui/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/app_flowy/packages/flowy_infra_ui/example/android/gradle/wrapper/gradle-wrapper.properties b/app_flowy/packages/flowy_infra_ui/example/android/gradle/wrapper/gradle-wrapper.properties index bc6a58afdd..b3e9099d2a 100644 --- a/app_flowy/packages/flowy_infra_ui/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/app_flowy/packages/flowy_infra_ui/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 23 08:50:38 CEST 2017 +#Sat Jul 17 23:27:26 CST 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip diff --git a/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Debug.xcconfig b/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Debug.xcconfig index 592ceee85b..ec97fc6f30 100644 --- a/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Debug.xcconfig +++ b/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Release.xcconfig b/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Release.xcconfig index 592ceee85b..c4855bfe20 100644 --- a/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Release.xcconfig +++ b/app_flowy/packages/flowy_infra_ui/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/app_flowy/packages/flowy_infra_ui/example/ios/Podfile b/app_flowy/packages/flowy_infra_ui/example/ios/Podfile new file mode 100644 index 0000000000..1e8c3c90a5 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/app_flowy/packages/flowy_infra_ui/example/ios/Podfile.lock b/app_flowy/packages/flowy_infra_ui/example/ios/Podfile.lock new file mode 100644 index 0000000000..c5a50f2dc9 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - flowy_infra_ui (0.0.1): + - Flutter + - Flutter (1.0.0) + +DEPENDENCIES: + - flowy_infra_ui (from `.symlinks/plugins/flowy_infra_ui/ios`) + - Flutter (from `Flutter`) + +EXTERNAL SOURCES: + flowy_infra_ui: + :path: ".symlinks/plugins/flowy_infra_ui/ios" + Flutter: + :path: Flutter + +SPEC CHECKSUMS: + flowy_infra_ui: 146c88346fd55d2ee6a41ae35059a5bf095cfbb3 + Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.9.3 diff --git a/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcodeproj/project.pbxproj b/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcodeproj/project.pbxproj index c6759a6e8f..bc3ced26c4 100644 --- a/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcodeproj/project.pbxproj +++ b/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + B061A1718EA00FC8FD116CB3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609D91DEF4C1832DC41DF975 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -31,7 +32,9 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 330E5DF8FFAD644160722BE7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 609D91DEF4C1832DC41DF975 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -42,6 +45,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E433772F3E94B24F3479C2F9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + F09BA83EC3ECFDE285785DB2 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -49,12 +54,32 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B061A1718EA00FC8FD116CB3 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 35285CDC74580BB1F9C79F75 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 609D91DEF4C1832DC41DF975 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 6F690F158B0591DDAF4BC371 /* Pods */ = { + isa = PBXGroup; + children = ( + 330E5DF8FFAD644160722BE7 /* Pods-Runner.debug.xcconfig */, + F09BA83EC3ECFDE285785DB2 /* Pods-Runner.release.xcconfig */, + E433772F3E94B24F3479C2F9 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +97,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + 6F690F158B0591DDAF4BC371 /* Pods */, + 35285CDC74580BB1F9C79F75 /* Frameworks */, ); sourceTree = ""; }; @@ -105,12 +132,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + DA35FF5721D34BC0BE4E1DD5 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 8A9E1CD9725728F74665B246 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -183,6 +212,24 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 8A9E1CD9725728F74665B246 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/flowy_infra_ui/flowy_infra_ui.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flowy_infra_ui.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -197,6 +244,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + DA35FF5721D34BC0BE4E1DD5 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -291,7 +360,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flowyInfraUiExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -415,7 +484,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flowyInfraUiExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -434,7 +503,7 @@ ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_BUNDLE_IDENTIFIER = com.example.flowyInfraUiExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed..21a3cc14c7 100644 --- a/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/app_flowy/packages/flowy_infra_ui/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/app_flowy/packages/flowy_infra_ui/example/ios/Runner/Info.plist b/app_flowy/packages/flowy_infra_ui/example/ios/Runner/Info.plist index a060db61e4..78bd1d1d6c 100644 --- a/app_flowy/packages/flowy_infra_ui/example/ios/Runner/Info.plist +++ b/app_flowy/packages/flowy_infra_ui/example/ios/Runner/Info.plist @@ -11,7 +11,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - example + flowy_infra_ui_example CFBundlePackageType APPL CFBundleShortVersionString diff --git a/app_flowy/packages/flowy_infra_ui/example/lib/home/demo_item.dart b/app_flowy/packages/flowy_infra_ui/example/lib/home/demo_item.dart new file mode 100644 index 0000000000..361e234231 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/lib/home/demo_item.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +abstract class ListItem {} + +abstract class DemoItem extends ListItem { + String buildTitle(); + + void handleTap(BuildContext context); +} + +class SectionHeaderItem extends ListItem { + SectionHeaderItem(this.title); + + final String title; + + Widget buildWidget(BuildContext context) => Text(title); +} diff --git a/app_flowy/packages/flowy_infra_ui/example/lib/home/home_screen.dart b/app_flowy/packages/flowy_infra_ui/example/lib/home/home_screen.dart new file mode 100644 index 0000000000..a6b4087417 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/lib/home/home_screen.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import '../keyboard/keyboard_screen.dart'; +import 'demo_item.dart'; + +class HomeScreen extends StatelessWidget { + const HomeScreen({Key? key}) : super(key: key); + + static List items = [ + SectionHeaderItem('Widget Demos'), + KeyboardItem(), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Demos'), + ), + body: ListView.builder( + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + if (item is SectionHeaderItem) { + return Container( + constraints: const BoxConstraints(maxHeight: 48.0), + color: Colors.grey[300], + alignment: Alignment.center, + child: ListTile( + title: Text(item.title), + ), + ); + } else if (item is DemoItem) { + return ListTile( + title: Text(item.buildTitle()), + onTap: () => item.handleTap(context), + ); + } + return const ListTile( + title: Text('Unknow.'), + ); + }, + ), + ); + } +} diff --git a/app_flowy/packages/flowy_infra_ui/example/lib/keyboard/keyboard_screen.dart b/app_flowy/packages/flowy_infra_ui/example/lib/keyboard/keyboard_screen.dart new file mode 100644 index 0000000000..28aa027b49 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/lib/keyboard/keyboard_screen.dart @@ -0,0 +1,78 @@ +import 'package:flowy_infra_ui/flowy_infra_ui_web.dart'; +import 'package:flutter/material.dart'; +import '../home/demo_item.dart'; + +class KeyboardItem extends DemoItem { + @override + String buildTitle() => 'Keyboard Listener'; + + @override + void handleTap(BuildContext context) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) { + return const KeyboardScreen(); + }, + ), + ); + } +} + +class KeyboardScreen extends StatefulWidget { + const KeyboardScreen({Key? key}) : super(key: key); + + @override + _KeyboardScreenState createState() => _KeyboardScreenState(); +} + +class _KeyboardScreenState extends State { + bool _isKeyboardVisible = false; + final TextEditingController _controller = TextEditingController(text: 'Hello Flowy'); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Keyboard Visibility Demo'), + ), + body: KeyboardVisibilityDetector( + onKeyboardVisibilityChange: (isKeyboardVisible) { + setState(() => _isKeyboardVisible = isKeyboardVisible); + }, + child: GestureDetector( + onTap: () => _dismissKeyboard(context), + behavior: HitTestBehavior.translucent, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 36), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 12.0), + child: Text( + 'Keyboard Visible: $_isKeyboardVisible', + style: const TextStyle(fontSize: 24.0), + ), + ), + TextField( + style: const TextStyle(fontSize: 20), + controller: _controller, + ), + ], + ), + ), + ), + ), + ), + ); + } + + void _dismissKeyboard(BuildContext context) { + final currentFocus = FocusScope.of(context); + + if (!currentFocus.hasPrimaryFocus && currentFocus.hasFocus) { + FocusManager.instance.primaryFocus?.unfocus(); + } + } +} diff --git a/app_flowy/packages/flowy_infra_ui/example/lib/main.dart b/app_flowy/packages/flowy_infra_ui/example/lib/main.dart index b31b2dcf48..1c3b2a41f4 100644 --- a/app_flowy/packages/flowy_infra_ui/example/lib/main.dart +++ b/app_flowy/packages/flowy_infra_ui/example/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'home/home_screen.dart'; void main() { runApp(const ExampleApp()); @@ -9,6 +10,9 @@ class ExampleApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp(); + return const MaterialApp( + title: "Flowy Infra Title", + home: HomeScreen(), + ); } } diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Debug.xcconfig b/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b608..4b81f9b2d2 100644 --- a/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Debug.xcconfig +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Release.xcconfig b/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Release.xcconfig index c2efd0b608..5caa9d1579 100644 --- a/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Release.xcconfig +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/GeneratedPluginRegistrant.swift b/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817a52..0c920d5387 100644 --- a/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import flowy_infra_ui func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FlowyInfraUIPlugin.register(with: registry.registrar(forPlugin: "FlowyInfraUIPlugin")) } diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Podfile b/app_flowy/packages/flowy_infra_ui/example/macos/Podfile new file mode 100644 index 0000000000..dade8dfad0 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.11' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Podfile.lock b/app_flowy/packages/flowy_infra_ui/example/macos/Podfile.lock new file mode 100644 index 0000000000..b0a2e1ef3a --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - flowy_infra_ui (0.0.1): + - FlutterMacOS + - FlutterMacOS (1.0.0) + +DEPENDENCIES: + - flowy_infra_ui (from `Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos`) + - FlutterMacOS (from `Flutter/ephemeral`) + +EXTERNAL SOURCES: + flowy_infra_ui: + :path: Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos + FlutterMacOS: + :path: Flutter/ephemeral + +SPEC CHECKSUMS: + flowy_infra_ui: 9d5021b1610fe0476eb1191bf7cd41c4a4138d8f + FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 + +PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c + +COCOAPODS: 1.9.3 diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/project.pbxproj b/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/project.pbxproj index cc89c87828..57fa2942d0 100644 --- a/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/project.pbxproj +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 7912A075158F80106DD95645 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0464B205D770E7A68F28B6D /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2D5900421C18B1A15A65A9EC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* flowy_infra_ui_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = flowy_infra_ui_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -68,6 +70,9 @@ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + 97A4E031C17F0C7BEEE33734 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + AB3F9417FEFE6929B49F80FE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + C0464B205D770E7A68F28B6D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,6 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7912A075158F80106DD95645 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,13 +105,14 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + A750A856115646FFDA1D1478 /* Pods */, ); sourceTree = ""; }; 33CC10EE2044A3C60003C045 /* Products */ = { isa = PBXGroup; children = ( - 33CC10ED2044A3C60003C045 /* example.app */, + 33CC10ED2044A3C60003C045 /* flowy_infra_ui_example.app */, ); name = Products; sourceTree = ""; @@ -145,9 +152,21 @@ path = Runner; sourceTree = ""; }; + A750A856115646FFDA1D1478 /* Pods */ = { + isa = PBXGroup; + children = ( + 97A4E031C17F0C7BEEE33734 /* Pods-Runner.debug.xcconfig */, + 2D5900421C18B1A15A65A9EC /* Pods-Runner.release.xcconfig */, + AB3F9417FEFE6929B49F80FE /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + C0464B205D770E7A68F28B6D /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 2FBE5781370B1EF78F66CD14 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 196EE237C3BE7811FE50A841 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -172,7 +193,7 @@ ); name = Runner; productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* example.app */; + productReference = 33CC10ED2044A3C60003C045 /* flowy_infra_ui_example.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -233,6 +254,45 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 196EE237C3BE7811FE50A841 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 2FBE5781370B1EF78F66CD14 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index ae8ff59d97..9420dfd1a6 100644 --- a/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -15,7 +15,7 @@ @@ -31,7 +31,7 @@ @@ -54,7 +54,7 @@ @@ -73,7 +73,7 @@ diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed..21a3cc14c7 100644 --- a/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/app_flowy/packages/flowy_infra_ui/example/macos/Runner/Configs/AppInfo.xcconfig b/app_flowy/packages/flowy_infra_ui/example/macos/Runner/Configs/AppInfo.xcconfig index cf9be60ca4..76ad650b99 100644 --- a/app_flowy/packages/flowy_infra_ui/example/macos/Runner/Configs/AppInfo.xcconfig +++ b/app_flowy/packages/flowy_infra_ui/example/macos/Runner/Configs/AppInfo.xcconfig @@ -5,10 +5,10 @@ // 'flutter create' template. // The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = example +PRODUCT_NAME = flowy_infra_ui_example // The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.example +PRODUCT_BUNDLE_IDENTIFIER = com.example.flowyInfraUiExample // The copyright displayed in application information PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved. diff --git a/app_flowy/packages/flowy_infra_ui/example/pubspec.lock b/app_flowy/packages/flowy_infra_ui/example/pubspec.lock index 510052ef08..c2685ea99f 100644 --- a/app_flowy/packages/flowy_infra_ui/example/pubspec.lock +++ b/app_flowy/packages/flowy_infra_ui/example/pubspec.lock @@ -99,6 +99,20 @@ packages: relative: true source: path version: "0.0.1" + flowy_infra_ui_platform_interface: + dependency: transitive + description: + path: "../flowy_infra_ui_platform_interface" + relative: true + source: path + version: "0.0.1" + flowy_infra_ui_web: + dependency: transitive + description: + path: "../flowy_infra_ui_web" + relative: true + source: path + version: "0.0.1" flutter: dependency: "direct main" description: flutter @@ -116,6 +130,18 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" lint: dependency: transitive description: @@ -165,6 +191,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" provider: dependency: transitive description: @@ -263,4 +296,4 @@ packages: version: "2.1.0" sdks: dart: ">=2.12.0 <3.0.0" - flutter: ">=1.17.0" + flutter: ">=1.20.0" diff --git a/app_flowy/packages/flowy_infra_ui/example/pubspec.yaml b/app_flowy/packages/flowy_infra_ui/example/pubspec.yaml index 90460cf69c..a747d1dc18 100644 --- a/app_flowy/packages/flowy_infra_ui/example/pubspec.yaml +++ b/app_flowy/packages/flowy_infra_ui/example/pubspec.yaml @@ -1,8 +1,7 @@ -name: example -description: A new Flutter project. +name: flowy_infra_ui_example +description: Demonstrates how to use the flowy_infra_ui plugin. -publish_to: 'none' -version: 1.0.0+1 +publish_to: 'none' # Remove this line if you wish to publish to pub.dev environment: sdk: ">=2.12.0 <3.0.0" @@ -11,11 +10,11 @@ dependencies: flutter: sdk: flutter - cupertino_icons: ^1.0.2 - flowy_infra_ui: path: ../ + cupertino_icons: ^1.0.2 + dev_dependencies: flutter_test: sdk: flutter @@ -23,4 +22,4 @@ dev_dependencies: flutter_lints: ^1.0.0 flutter: - uses-material-design: true \ No newline at end of file + uses-material-design: true diff --git a/app_flowy/packages/flowy_infra_ui/example/test/widget_test.dart b/app_flowy/packages/flowy_infra_ui/example/test/widget_test.dart index ceaa592386..1550d94848 100644 --- a/app_flowy/packages/flowy_infra_ui/example/test/widget_test.dart +++ b/app_flowy/packages/flowy_infra_ui/example/test/widget_test.dart @@ -8,23 +8,19 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:example/main.dart'; +import 'package:flowy_infra_ui_example/main.dart'; void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { + testWidgets('Verify Platform version', (WidgetTester tester) async { // Build our app and trigger a frame. await tester.pumpWidget(const ExampleApp()); - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => widget is Text && widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); }); } diff --git a/app_flowy/packages/flowy_infra_ui/example/web/index.html b/app_flowy/packages/flowy_infra_ui/example/web/index.html index eed169dc70..dda953d8dd 100644 --- a/app_flowy/packages/flowy_infra_ui/example/web/index.html +++ b/app_flowy/packages/flowy_infra_ui/example/web/index.html @@ -18,15 +18,15 @@ - + - + - example + flowy_infra_ui_example diff --git a/app_flowy/packages/flowy_infra_ui/example/web/manifest.json b/app_flowy/packages/flowy_infra_ui/example/web/manifest.json index 8c012917da..5c3b6fad3c 100644 --- a/app_flowy/packages/flowy_infra_ui/example/web/manifest.json +++ b/app_flowy/packages/flowy_infra_ui/example/web/manifest.json @@ -1,11 +1,11 @@ { - "name": "example", - "short_name": "example", + "name": "flowy_infra_ui_example", + "short_name": "flowy_infra_ui_example", "start_url": ".", "display": "standalone", "background_color": "#0175C2", "theme_color": "#0175C2", - "description": "A new Flutter project.", + "description": "Demonstrates how to use the flowy_infra_ui plugin.", "orientation": "portrait-primary", "prefer_related_applications": false, "icons": [ diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/.gitignore b/app_flowy/packages/flowy_infra_ui/example/windows/.gitignore new file mode 100644 index 0000000000..d492d0d98c --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/CMakeLists.txt b/app_flowy/packages/flowy_infra_ui/example/windows/CMakeLists.txt new file mode 100644 index 0000000000..50d22a91d1 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(flowy_infra_ui_example LANGUAGES CXX) + +set(BINARY_NAME "flowy_infra_ui_example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/flutter/CMakeLists.txt b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000000..b02c5485c9 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugin_registrant.cc b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000..0f8fb4aef5 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FlowyInfraUIPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlowyInfraUIPlugin")); +} diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugin_registrant.h b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000..9846246b4d --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,13 @@ +// +// Generated file. Do not edit. +// + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugins.cmake b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000000..c82a15ca3f --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,16 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + flowy_infra_ui +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/CMakeLists.txt b/app_flowy/packages/flowy_infra_ui/example/windows/runner/CMakeLists.txt new file mode 100644 index 0000000000..0b899a0bcf --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/Runner.rc b/app_flowy/packages/flowy_infra_ui/example/windows/runner/Runner.rc new file mode 100644 index 0000000000..7db52c01ae --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "Demonstrates how to use the flowy_infra_ui plugin." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "flowy_infra_ui_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "flowy_infra_ui_example.exe" "\0" + VALUE "ProductName", "flowy_infra_ui_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/flutter_window.cpp b/app_flowy/packages/flowy_infra_ui/example/windows/runner/flutter_window.cpp new file mode 100644 index 0000000000..b43b9095ea --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/flutter_window.h b/app_flowy/packages/flowy_infra_ui/example/windows/runner/flutter_window.h new file mode 100644 index 0000000000..6da0652f05 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/main.cpp b/app_flowy/packages/flowy_infra_ui/example/windows/runner/main.cpp new file mode 100644 index 0000000000..a1b7c151e3 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"flowy_infra_ui_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/resource.h b/app_flowy/packages/flowy_infra_ui/example/windows/runner/resource.h new file mode 100644 index 0000000000..66a65d1e4a --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/resources/app_icon.ico b/app_flowy/packages/flowy_infra_ui/example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000..c04e20caf6 Binary files /dev/null and b/app_flowy/packages/flowy_infra_ui/example/windows/runner/resources/app_icon.ico differ diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/runner.exe.manifest b/app_flowy/packages/flowy_infra_ui/example/windows/runner/runner.exe.manifest new file mode 100644 index 0000000000..c977c4a425 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/utils.cpp b/app_flowy/packages/flowy_infra_ui/example/windows/runner/utils.cpp new file mode 100644 index 0000000000..d19bdbbcc3 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/utils.h b/app_flowy/packages/flowy_infra_ui/example/windows/runner/utils.h new file mode 100644 index 0000000000..3879d54755 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/win32_window.cpp b/app_flowy/packages/flowy_infra_ui/example/windows/runner/win32_window.cpp new file mode 100644 index 0000000000..c10f08dc7d --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app_flowy/packages/flowy_infra_ui/example/windows/runner/win32_window.h b/app_flowy/packages/flowy_infra_ui/example/windows/runner/win32_window.h new file mode 100644 index 0000000000..17ba431125 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/example/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/.gitignore b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/.gitignore new file mode 100644 index 0000000000..a247422ef7 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/.gitignore @@ -0,0 +1,75 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/ephemeral +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/.metadata b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/.metadata new file mode 100644 index 0000000000..f46c92994f --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: fa5883b78e566877613ad1ccb48dd92075cb5c23 + channel: dev + +project_type: package diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/CHANGELOG.md b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/CHANGELOG.md new file mode 100644 index 0000000000..41cc7d8192 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/LICENSE b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/LICENSE new file mode 100644 index 0000000000..ba75c69f7f --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/README.md b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/README.md new file mode 100644 index 0000000000..d4b7622cef --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/README.md @@ -0,0 +1,14 @@ +# flowy_infra_ui_platform_interface + +A new Flutter package project. + +## Getting Started + +This project is a starting point for a Dart +[package](https://flutter.dev/developing-packages/), +a library module containing code that can be shared easily across +multiple Flutter or Dart projects. + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/analysis_options.yaml b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/analysis_options.yaml new file mode 100644 index 0000000000..a5744c1cfb --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/lib/flowy_infra_ui_platform_interface.dart b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/lib/flowy_infra_ui_platform_interface.dart new file mode 100644 index 0000000000..32ac147886 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/lib/flowy_infra_ui_platform_interface.dart @@ -0,0 +1,27 @@ +library flowy_infra_ui_platform_interface; + +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'src/method_channel_flowy_infra_ui.dart'; + +abstract class FlowyInfraUIPlatform extends PlatformInterface { + FlowyInfraUIPlatform() : super(token: _token); + + static final Object _token = Object(); + + static FlowyInfraUIPlatform _instance = MethodChannelFlowyInfraUI(); + + static FlowyInfraUIPlatform get instance => _instance; + + static set instance(FlowyInfraUIPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + Stream get onKeyboardVisibilityChange { + throw UnimplementedError('`onKeyboardChange` should be overrided by subclass.'); + } + + Future getPlatformVersion() { + throw UnimplementedError('`getPlatformVersion` should be overrided by subclass.'); + } +} diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/lib/src/method_channel_flowy_infra_ui.dart b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/lib/src/method_channel_flowy_infra_ui.dart new file mode 100644 index 0000000000..ad8051f515 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/lib/src/method_channel_flowy_infra_ui.dart @@ -0,0 +1,26 @@ +import 'package:flowy_infra_ui_platform_interface/flowy_infra_ui_platform_interface.dart'; +import 'package:flutter/services.dart'; + +import '../flowy_infra_ui_platform_interface.dart'; + +// ignore_for_file: constant_identifier_names +const INFRA_UI_METHOD_CHANNEL_NAME = 'flowy_infra_ui_method'; +const INFRA_UI_KEYBOARD_EVENT_CHANNEL_NAME = 'flowy_infra_ui_event/keyboard'; +const INFRA_UI_METHOD_GET_PLATFORM_VERSION = 'getPlatformVersion'; + +class MethodChannelFlowyInfraUI extends FlowyInfraUIPlatform { + final MethodChannel _methodChannel = const MethodChannel(INFRA_UI_METHOD_CHANNEL_NAME); + final EventChannel _keyboardChannel = const EventChannel(INFRA_UI_KEYBOARD_EVENT_CHANNEL_NAME); + + late final Stream _onKeyboardVisibilityChange = + _keyboardChannel.receiveBroadcastStream().map((event) => event as bool); + + @override + Stream get onKeyboardVisibilityChange => _onKeyboardVisibilityChange; + + @override + Future getPlatformVersion() async { + String? version = await _methodChannel.invokeMethod(INFRA_UI_METHOD_GET_PLATFORM_VERSION); + return version ?? 'unknow'; + } +} diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.lock b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.lock new file mode 100644 index 0000000000..a2ed8a8fe8 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.lock @@ -0,0 +1,168 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.6.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + plugin_platform_interface: + dependency: "direct main" + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" +sdks: + dart: ">=2.12.0 <3.0.0" + flutter: ">=1.17.0" diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.yaml b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.yaml new file mode 100644 index 0000000000..0b5f8eb74b --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/pubspec.yaml @@ -0,0 +1,21 @@ +name: flowy_infra_ui_platform_interface +description: A new Flutter package project. +version: 0.0.1 +homepage: + +environment: + sdk: ">=2.12.0 <3.0.0" + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + + plugin_platform_interface: ^2.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^1.0.0 + +flutter: \ No newline at end of file diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/test/flowy_infra_ui_platform_interface_test.dart b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/test/flowy_infra_ui_platform_interface_test.dart new file mode 100644 index 0000000000..b351001e1a --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_platform_interface/test/flowy_infra_ui_platform_interface_test.dart @@ -0,0 +1,5 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flowy_infra_ui_platform_interface/flowy_infra_ui_platform_interface.dart'; + +void main() {} diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/.gitignore b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/.gitignore new file mode 100644 index 0000000000..a247422ef7 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/.gitignore @@ -0,0 +1,75 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/ephemeral +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/.metadata b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/.metadata new file mode 100644 index 0000000000..f46c92994f --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: fa5883b78e566877613ad1ccb48dd92075cb5c23 + channel: dev + +project_type: package diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/CHANGELOG.md b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/CHANGELOG.md new file mode 100644 index 0000000000..41cc7d8192 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/LICENSE b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/LICENSE new file mode 100644 index 0000000000..ba75c69f7f --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/README.md b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/README.md new file mode 100644 index 0000000000..b552d83994 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/README.md @@ -0,0 +1,14 @@ +# flowy_infra_ui_web + +A new Flutter package project. + +## Getting Started + +This project is a starting point for a Dart +[package](https://flutter.dev/developing-packages/), +a library module containing code that can be shared easily across +multiple Flutter or Dart projects. + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/analysis_options.yaml b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/analysis_options.yaml new file mode 100644 index 0000000000..a5744c1cfb --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/lib/flowy_infra_ui_web.dart b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/lib/flowy_infra_ui_web.dart new file mode 100644 index 0000000000..e3bd3a2fe0 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/lib/flowy_infra_ui_web.dart @@ -0,0 +1,25 @@ +library flowy_infra_ui_web; + +import 'dart:html' as html show window; +import 'package:flowy_infra_ui_platform_interface/flowy_infra_ui_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +class FlowyInfraUIPlugin extends FlowyInfraUIPlatform { + static void registerWith(Registrar registrar) { + FlowyInfraUIPlatform.instance = FlowyInfraUIPlugin(); + } + + // MARK: - Keyboard + + @override + Stream get onKeyboardVisibilityChange async* { + // suppose that keyboard won't show in web side + yield false; + } + + @override + Future getPlatformVersion() async { + final version = html.window.navigator.userAgent; + return Future.value(version); + } +} diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.lock b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.lock new file mode 100644 index 0000000000..804b67b5b9 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.lock @@ -0,0 +1,187 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.6.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + flowy_infra_ui_platform_interface: + dependency: "direct main" + description: + path: "../flowy_infra_ui_platform_interface" + relative: true + source: path + version: "0.0.1" + flutter: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" +sdks: + dart: ">=2.12.0 <3.0.0" + flutter: ">=1.17.0" diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.yaml b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.yaml new file mode 100644 index 0000000000..03600f2e5a --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/pubspec.yaml @@ -0,0 +1,28 @@ +name: flowy_infra_ui_web +description: A new Flutter package project. +version: 0.0.1 +homepage: +publish_to: none + +environment: + sdk: ">=2.12.0 <3.0.0" + flutter: ">=1.17.0" + +dependencies: + flutter_web_plugins: + sdk: flutter + + flowy_infra_ui_platform_interface: + path: ../flowy_infra_ui_platform_interface + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^1.0.0 + +flutter: + plugin: + platforms: + web: + pluginClass: FlowyInfraUIPlugin + fileName: flowy_infra_ui_web.dart \ No newline at end of file diff --git a/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/test/flowy_infra_ui_web_test.dart b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/test/flowy_infra_ui_web_test.dart new file mode 100644 index 0000000000..a9de9b8be5 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/flowy_infra_ui_web/test/flowy_infra_ui_web_test.dart @@ -0,0 +1,5 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flowy_infra_ui_web/flowy_infra_ui_web.dart'; + +void main() {} diff --git a/app_flowy/packages/flowy_infra_ui/ios/.gitignore b/app_flowy/packages/flowy_infra_ui/ios/.gitignore new file mode 100644 index 0000000000..0c885071e3 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/ios/.gitignore @@ -0,0 +1,38 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/ephemeral/ +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/app_flowy/packages/flowy_infra_ui/ios/Assets/.gitkeep b/app_flowy/packages/flowy_infra_ui/ios/Assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app_flowy/packages/flowy_infra_ui/ios/Classes/Event/KeyboardEventHandler.swift b/app_flowy/packages/flowy_infra_ui/ios/Classes/Event/KeyboardEventHandler.swift new file mode 100644 index 0000000000..6f7e1f4b25 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/ios/Classes/Event/KeyboardEventHandler.swift @@ -0,0 +1,85 @@ +// +// KeyboardEventHandler.swift +// flowy_infra_ui +// +// Created by Jaylen Bian on 7/17/21. +// + +class KeyboardEventHandler: NSObject, FlutterStreamHandler { + + var isKeyboardShow: Bool = false + var eventSink: FlutterEventSink? + + override init() { + super.init() + + NotificationCenter.default.addObserver( + self, + selector: #selector(handleKeyboardWillShow), + name: UIApplication.keyboardWillShowNotification, + object: nil) + NotificationCenter.default.addObserver( + self, + selector: #selector(handleKeyboardDidShow), + name: UIApplication.keyboardDidShowNotification, + object: nil) + NotificationCenter.default.addObserver( + self, + selector: #selector(handleKeyboardWillHide), + name: UIApplication.keyboardWillHideNotification, + object: nil) + NotificationCenter.default.addObserver( + self, + selector: #selector(handleKeyboardDidHide), + name: UIApplication.keyboardDidHideNotification, + object: nil) + } + + func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { + eventSink = events + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + eventSink = nil + return nil + } + + // MARK: Helper + + @objc + private func handleKeyboardWillShow() { + guard !isKeyboardShow else { + return + } + isKeyboardShow = true + eventSink?(NSNumber(booleanLiteral: true)) + } + + @objc + private func handleKeyboardDidShow() { + guard !isKeyboardShow else { + return + } + isKeyboardShow = true + eventSink?(NSNumber(booleanLiteral: true)) + } + + @objc + private func handleKeyboardWillHide() { + guard isKeyboardShow else { + return + } + isKeyboardShow = false + eventSink?(NSNumber(booleanLiteral: false)) + } + + @objc + private func handleKeyboardDidHide() { + guard isKeyboardShow else { + return + } + isKeyboardShow = false + eventSink?(NSNumber(booleanLiteral: false)) + } +} diff --git a/app_flowy/packages/flowy_infra_ui/ios/Classes/FlowyInfraUIPlugin.h b/app_flowy/packages/flowy_infra_ui/ios/Classes/FlowyInfraUIPlugin.h new file mode 100644 index 0000000000..51f5d35106 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/ios/Classes/FlowyInfraUIPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FlowyInfraUIPlugin : NSObject +@end diff --git a/app_flowy/packages/flowy_infra_ui/ios/Classes/FlowyInfraUIPlugin.m b/app_flowy/packages/flowy_infra_ui/ios/Classes/FlowyInfraUIPlugin.m new file mode 100644 index 0000000000..58f19ce516 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/ios/Classes/FlowyInfraUIPlugin.m @@ -0,0 +1,15 @@ +#import "FlowyInfraUIPlugin.h" +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "flowy_infra_ui-Swift.h" +#endif + +@implementation FlowyInfraUIPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftFlowyInfraUIPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/app_flowy/packages/flowy_infra_ui/ios/Classes/SwiftFlowyInfraUIPlugin.swift b/app_flowy/packages/flowy_infra_ui/ios/Classes/SwiftFlowyInfraUIPlugin.swift new file mode 100644 index 0000000000..641a0e53c2 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/ios/Classes/SwiftFlowyInfraUIPlugin.swift @@ -0,0 +1,38 @@ +import Flutter +import UIKit + +public class SwiftFlowyInfraUIPlugin: NSObject, FlutterPlugin { + + enum Constant { + static let infraUIMethodChannelName = "flowy_infra_ui_method" + static let infraUIKeyboardEventChannelName = "flowy_infra_ui_event/keyboard" + + static let infraUIMethodGetPlatformVersion = "getPlatformVersion" + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let instance = SwiftFlowyInfraUIPlugin() + + let methodChannel = FlutterMethodChannel( + name: Constant.infraUIMethodChannelName, + binaryMessenger: registrar.messenger()) + registrar.addMethodCallDelegate(instance, channel: methodChannel) + + let keyboardEventChannel = FlutterEventChannel( + name: Constant.infraUIKeyboardEventChannelName, + binaryMessenger: registrar.messenger()) + keyboardEventChannel.setStreamHandler(KeyboardEventHandler()) + } + + // MARK: - Method Channel + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case Constant.infraUIMethodGetPlatformVersion: + result("iOS " + UIDevice.current.systemVersion) + default: + result(FlutterMethodNotImplemented) + } + } + +} diff --git a/app_flowy/packages/flowy_infra_ui/ios/flowy_infra_ui.podspec b/app_flowy/packages/flowy_infra_ui/ios/flowy_infra_ui.podspec new file mode 100644 index 0000000000..767ae7c3cd --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/ios/flowy_infra_ui.podspec @@ -0,0 +1,23 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint flowy_infra_ui.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'flowy_infra_ui' + s.version = '0.0.1' + s.summary = 'A new flutter plugin project.' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '8.0' + + # Flutter.framework does not contain a i386 slice. + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } + s.swift_version = '5.0' +end diff --git a/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui.dart b/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui.dart new file mode 100644 index 0000000000..36a2148c07 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui.dart @@ -0,0 +1,2 @@ +// Keyboard +export 'src/keyboard/keyboard_visibility_detector.dart'; diff --git a/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui_web.dart b/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui_web.dart new file mode 100644 index 0000000000..36a2148c07 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/lib/flowy_infra_ui_web.dart @@ -0,0 +1,2 @@ +// Keyboard +export 'src/keyboard/keyboard_visibility_detector.dart'; diff --git a/app_flowy/packages/flowy_infra_ui/lib/src/focus/auto_unfocus_overlay.dart b/app_flowy/packages/flowy_infra_ui/lib/src/focus/auto_unfocus_overlay.dart new file mode 100644 index 0000000000..45faebc07d --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/lib/src/focus/auto_unfocus_overlay.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class AutoUnfocus extends StatelessWidget { + const AutoUnfocus({ + Key? key, + required this.child, + }) : super(key: key); + + final Widget child; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => _unfocusWidget(context), + child: child, + ); + } + + void _unfocusWidget(BuildContext context) { + final focusing = FocusScope.of(context); + + if (!focusing.hasPrimaryFocus && focusing.hasFocus) { + FocusManager.instance.primaryFocus?.unfocus(); + } + } +} diff --git a/app_flowy/packages/flowy_infra_ui/lib/src/keyboard/keyboard_visibility_detector.dart b/app_flowy/packages/flowy_infra_ui/lib/src/keyboard/keyboard_visibility_detector.dart new file mode 100644 index 0000000000..b4d084acc0 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/lib/src/keyboard/keyboard_visibility_detector.dart @@ -0,0 +1,68 @@ +import 'dart:async'; + +import 'package:flowy_infra_ui_platform_interface/flowy_infra_ui_platform_interface.dart'; +import 'package:flutter/material.dart'; + +class KeyboardVisibilityDetector extends StatefulWidget { + const KeyboardVisibilityDetector({ + Key? key, + required this.child, + this.onKeyboardVisibilityChange, + }) : super(key: key); + + final Widget child; + final void Function(bool)? onKeyboardVisibilityChange; + + @override + _KeyboardVisibilityDetectorState createState() => _KeyboardVisibilityDetectorState(); +} + +class _KeyboardVisibilityDetectorState extends State { + FlowyInfraUIPlatform get _platform => FlowyInfraUIPlatform.instance; + + bool isObserving = false; + bool isKeyboardVisible = false; + late StreamSubscription _keyboardSubscription; + + @override + void initState() { + super.initState(); + _keyboardSubscription = _platform.onKeyboardVisibilityChange.listen((newValue) { + setState(() { + isKeyboardVisible = newValue; + if (widget.onKeyboardVisibilityChange != null) { + widget.onKeyboardVisibilityChange!(newValue); + } + }); + }); + } + + @override + void dispose() { + _keyboardSubscription.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return _KeyboardVisibilityDetectorInheritedWidget( + isKeyboardVisible: isKeyboardVisible, + child: widget.child, + ); + } +} + +class _KeyboardVisibilityDetectorInheritedWidget extends InheritedWidget { + const _KeyboardVisibilityDetectorInheritedWidget({ + Key? key, + required this.isKeyboardVisible, + required Widget child, + }) : super(key: key, child: child); + + final bool isKeyboardVisible; + + @override + bool updateShouldNotify(_KeyboardVisibilityDetectorInheritedWidget oldWidget) { + return isKeyboardVisible != oldWidget.isKeyboardVisible; + } +} diff --git a/app_flowy/packages/flowy_infra_ui/lib/src/overlay/overlay_widget.dart b/app_flowy/packages/flowy_infra_ui/lib/src/overlay/overlay_widget.dart index e69de29bb2..8d7b427e9b 100644 --- a/app_flowy/packages/flowy_infra_ui/lib/src/overlay/overlay_widget.dart +++ b/app_flowy/packages/flowy_infra_ui/lib/src/overlay/overlay_widget.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class Overlay extends StatelessWidget { + const Overlay({ + Key? key, + this.safeAreaEnabled = true, + }) : super(key: key); + + final bool safeAreaEnabled; + + @override + Widget build(BuildContext context) { + return Container(); + } +} diff --git a/app_flowy/packages/flowy_infra_ui/macos/Classes/FlowyInfraUiPlugin.swift b/app_flowy/packages/flowy_infra_ui/macos/Classes/FlowyInfraUiPlugin.swift new file mode 100644 index 0000000000..a18610dede --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/macos/Classes/FlowyInfraUiPlugin.swift @@ -0,0 +1,19 @@ +import Cocoa +import FlutterMacOS + +public class FlowyInfraUIPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "flowy_infra_ui", binaryMessenger: registrar.messenger) + let instance = FlowyInfraUIPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getPlatformVersion": + result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString) + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/app_flowy/packages/flowy_infra_ui/macos/flowy_infra_ui.podspec b/app_flowy/packages/flowy_infra_ui/macos/flowy_infra_ui.podspec new file mode 100644 index 0000000000..2dd79403f1 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/macos/flowy_infra_ui.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint flowy_infra_ui.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'flowy_infra_ui' + s.version = '0.0.1' + s.summary = 'A new flutter plugin project.' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'FlutterMacOS' + + s.platform = :osx, '10.11' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' +end diff --git a/app_flowy/packages/flowy_infra_ui/pubspec.lock b/app_flowy/packages/flowy_infra_ui/pubspec.lock index 87940a591f..98f80cfe2a 100644 --- a/app_flowy/packages/flowy_infra_ui/pubspec.lock +++ b/app_flowy/packages/flowy_infra_ui/pubspec.lock @@ -85,6 +85,20 @@ packages: relative: true source: path version: "0.0.1" + flowy_infra_ui_platform_interface: + dependency: "direct main" + description: + path: flowy_infra_ui_platform_interface + relative: true + source: path + version: "0.0.1" + flowy_infra_ui_web: + dependency: "direct main" + description: + path: flowy_infra_ui_web + relative: true + source: path + version: "0.0.1" flutter: dependency: "direct main" description: flutter @@ -102,6 +116,18 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" lint: dependency: transitive description: @@ -151,6 +177,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" provider: dependency: "direct main" description: @@ -249,4 +282,4 @@ packages: version: "2.1.0" sdks: dart: ">=2.12.0 <3.0.0" - flutter: ">=1.17.0" + flutter: ">=1.20.0" diff --git a/app_flowy/packages/flowy_infra_ui/pubspec.yaml b/app_flowy/packages/flowy_infra_ui/pubspec.yaml index bc7007349b..fec0ebe4a1 100644 --- a/app_flowy/packages/flowy_infra_ui/pubspec.yaml +++ b/app_flowy/packages/flowy_infra_ui/pubspec.yaml @@ -1,22 +1,32 @@ name: flowy_infra_ui -description: A new Flutter package project. +description: A new flutter plugin project. version: 0.0.1 homepage: publish_to: 'none' environment: sdk: ">=2.12.0 <3.0.0" - flutter: ">=1.17.0" + flutter: ">=1.20.0" dependencies: flutter: sdk: flutter + + # Thirdparty packages textstyle_extensions: '2.0.0-nullsafety' dartz: '0.10.0-nullsafety.2' provider: ^5.0.0 styled_widget: '>=0.3.1' equatable: '>=2.0.2' animations: ^2.0.0 + + # Federated Platform Interface + flowy_infra_ui_platform_interface: + path: flowy_infra_ui_platform_interface + flowy_infra_ui_web: + path: flowy_infra_ui_web + + # Flowy packages flowy_infra: path: ../flowy_infra @@ -24,41 +34,18 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^1.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: - - # To add assets to your package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/custom-fonts/#from-packages + plugin: + platforms: + android: + package: com.example.flowy_infra_ui + pluginClass: FlowyInfraUIPlugin + ios: + pluginClass: FlowyInfraUIPlugin + macos: + pluginClass: FlowyInfraUIPlugin + windows: + pluginClass: FlowyInfraUIPlugin + web: + default_package: flowy_infra_ui_web \ No newline at end of file diff --git a/app_flowy/packages/flowy_infra_ui/test/flowy_infra_ui_test.dart b/app_flowy/packages/flowy_infra_ui/test/flowy_infra_ui_test.dart new file mode 100644 index 0000000000..c7e2a4cf99 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/test/flowy_infra_ui_test.dart @@ -0,0 +1,23 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; + +void main() { + const MethodChannel channel = MethodChannel('flowy_infra_ui'); + + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + channel.setMockMethodCallHandler((MethodCall methodCall) async { + return '42'; + }); + }); + + tearDown(() { + channel.setMockMethodCallHandler(null); + }); + + test('getPlatformVersion', () async { + expect(await FlowyInfraUi.platformVersion, '42'); + }); +} diff --git a/app_flowy/packages/flowy_infra_ui/test/flowy_ui_test.dart b/app_flowy/packages/flowy_infra_ui/test/flowy_ui_test.dart deleted file mode 100644 index 8b13789179..0000000000 --- a/app_flowy/packages/flowy_infra_ui/test/flowy_ui_test.dart +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app_flowy/packages/flowy_infra_ui/windows/.gitignore b/app_flowy/packages/flowy_infra_ui/windows/.gitignore new file mode 100644 index 0000000000..b3eb2be169 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/app_flowy/packages/flowy_infra_ui/windows/CMakeLists.txt b/app_flowy/packages/flowy_infra_ui/windows/CMakeLists.txt new file mode 100644 index 0000000000..27ce69d238 --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/windows/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.15) +set(PROJECT_NAME "flowy_infra_ui") +project(${PROJECT_NAME} LANGUAGES CXX) + +# This value is used when generating builds using this plugin, so it must +# not be changed +set(PLUGIN_NAME "flowy_infra_ui_plugin") + +add_library(${PLUGIN_NAME} SHARED + "flowy_infra_ui_plugin.cpp" +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) + +# List of absolute paths to libraries that should be bundled with the plugin +set(flowy_infra_ui_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/app_flowy/packages/flowy_infra_ui/windows/flowy_infra_ui_plugin.cpp b/app_flowy/packages/flowy_infra_ui/windows/flowy_infra_ui_plugin.cpp new file mode 100644 index 0000000000..4de31d554f --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/windows/flowy_infra_ui_plugin.cpp @@ -0,0 +1,82 @@ +#include "include/flowy_infra_ui/flowy_infra_ui_plugin.h" + +// This must be included before many other Windows headers. +#include + +// For getPlatformVersion; remove unless needed for your plugin implementation. +#include + +#include +#include +#include + +#include +#include +#include + +namespace { + +class FlowyInfraUIPlugin : public flutter::Plugin { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + + FlowyInfraUIPlugin(); + + virtual ~FlowyInfraUIPlugin(); + + private: + // Called when a method is called on this plugin's channel from Dart. + void HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr> result); +}; + +// static +void FlowyInfraUIPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + auto channel = + std::make_unique>( + registrar->messenger(), "flowy_infra_ui", + &flutter::StandardMethodCodec::GetInstance()); + + auto plugin = std::make_unique(); + + channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + registrar->AddPlugin(std::move(plugin)); +} + +FlowyInfraUIPlugin::FlowyInfraUIPlugin() {} + +FlowyInfraUIPlugin::~FlowyInfraUIPlugin() {} + +void FlowyInfraUIPlugin::HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr> result) { + if (method_call.method_name().compare("getPlatformVersion") == 0) { + std::ostringstream version_stream; + version_stream << "Windows "; + if (IsWindows10OrGreater()) { + version_stream << "10+"; + } else if (IsWindows8OrGreater()) { + version_stream << "8"; + } else if (IsWindows7OrGreater()) { + version_stream << "7"; + } + result->Success(flutter::EncodableValue(version_stream.str())); + } else { + result->NotImplemented(); + } +} + +} // namespace + +void FlowyInfraUIPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + FlowyInfraUIPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app_flowy/packages/flowy_infra_ui/windows/include/flowy_infra_ui/flowy_infra_ui_plugin.h b/app_flowy/packages/flowy_infra_ui/windows/include/flowy_infra_ui/flowy_infra_ui_plugin.h new file mode 100644 index 0000000000..475039941f --- /dev/null +++ b/app_flowy/packages/flowy_infra_ui/windows/include/flowy_infra_ui/flowy_infra_ui_plugin.h @@ -0,0 +1,23 @@ +#ifndef FLUTTER_PLUGIN_FLOWY_INFRA_UI_PLUGIN_H_ +#define FLUTTER_PLUGIN_FLOWY_INFRA_UI_PLUGIN_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void FlowyInfraUIPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_PLUGIN_FLOWY_INFRA_UI_PLUGIN_H_ diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart index 9b07cc71c3..28205f8984 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart @@ -11,11 +11,11 @@ import 'package:protobuf/protobuf.dart' as $pb; class UserErrorCode extends $pb.ProtobufEnum { static const UserErrorCode Unknown = UserErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown'); - static const UserErrorCode DatabaseInitFailed = UserErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseInitFailed'); - static const UserErrorCode DatabaseWriteLocked = UserErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseWriteLocked'); - static const UserErrorCode DatabaseReadLocked = UserErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseReadLocked'); - static const UserErrorCode DatabaseUserDidNotMatch = UserErrorCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseUserDidNotMatch'); - static const UserErrorCode DatabaseInternalError = UserErrorCode._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseInternalError'); + static const UserErrorCode UserDatabaseInitFailed = UserErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseInitFailed'); + static const UserErrorCode UserDatabaseWriteLocked = UserErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseWriteLocked'); + static const UserErrorCode UserDatabaseReadLocked = UserErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseReadLocked'); + static const UserErrorCode UserDatabaseDidNotMatch = UserErrorCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseDidNotMatch'); + static const UserErrorCode UserDatabaseInternalError = UserErrorCode._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseInternalError'); static const UserErrorCode UserNotLoginYet = UserErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotLoginYet'); static const UserErrorCode ReadCurrentIdFailed = UserErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadCurrentIdFailed'); static const UserErrorCode WriteCurrentIdFailed = UserErrorCode._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WriteCurrentIdFailed'); @@ -24,14 +24,15 @@ class UserErrorCode extends $pb.ProtobufEnum { static const UserErrorCode UserNameInvalid = UserErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameInvalid'); static const UserErrorCode UserWorkspaceInvalid = UserErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserWorkspaceInvalid'); static const UserErrorCode UserIdInvalid = UserErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid'); + static const UserErrorCode CreateDefaultWorkspaceFailed = UserErrorCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultWorkspaceFailed'); static const $core.List values = [ Unknown, - DatabaseInitFailed, - DatabaseWriteLocked, - DatabaseReadLocked, - DatabaseUserDidNotMatch, - DatabaseInternalError, + UserDatabaseInitFailed, + UserDatabaseWriteLocked, + UserDatabaseReadLocked, + UserDatabaseDidNotMatch, + UserDatabaseInternalError, UserNotLoginYet, ReadCurrentIdFailed, WriteCurrentIdFailed, @@ -40,6 +41,7 @@ class UserErrorCode extends $pb.ProtobufEnum { UserNameInvalid, UserWorkspaceInvalid, UserIdInvalid, + CreateDefaultWorkspaceFailed, ]; static final $core.Map<$core.int, UserErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart index 217cb44134..70e80819c6 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart @@ -13,11 +13,11 @@ const UserErrorCode$json = const { '1': 'UserErrorCode', '2': const [ const {'1': 'Unknown', '2': 0}, - const {'1': 'DatabaseInitFailed', '2': 1}, - const {'1': 'DatabaseWriteLocked', '2': 2}, - const {'1': 'DatabaseReadLocked', '2': 3}, - const {'1': 'DatabaseUserDidNotMatch', '2': 4}, - const {'1': 'DatabaseInternalError', '2': 5}, + const {'1': 'UserDatabaseInitFailed', '2': 1}, + const {'1': 'UserDatabaseWriteLocked', '2': 2}, + const {'1': 'UserDatabaseReadLocked', '2': 3}, + const {'1': 'UserDatabaseDidNotMatch', '2': 4}, + const {'1': 'UserDatabaseInternalError', '2': 5}, const {'1': 'UserNotLoginYet', '2': 10}, const {'1': 'ReadCurrentIdFailed', '2': 11}, const {'1': 'WriteCurrentIdFailed', '2': 12}, @@ -26,11 +26,12 @@ const UserErrorCode$json = const { const {'1': 'UserNameInvalid', '2': 22}, const {'1': 'UserWorkspaceInvalid', '2': 23}, const {'1': 'UserIdInvalid', '2': 24}, + const {'1': 'CreateDefaultWorkspaceFailed', '2': 25}, ], }; /// Descriptor for `UserErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List userErrorCodeDescriptor = $convert.base64Decode('Cg1Vc2VyRXJyb3JDb2RlEgsKB1Vua25vd24QABIWChJEYXRhYmFzZUluaXRGYWlsZWQQARIXChNEYXRhYmFzZVdyaXRlTG9ja2VkEAISFgoSRGF0YWJhc2VSZWFkTG9ja2VkEAMSGwoXRGF0YWJhc2VVc2VyRGlkTm90TWF0Y2gQBBIZChVEYXRhYmFzZUludGVybmFsRXJyb3IQBRITCg9Vc2VyTm90TG9naW5ZZXQQChIXChNSZWFkQ3VycmVudElkRmFpbGVkEAsSGAoUV3JpdGVDdXJyZW50SWRGYWlsZWQQDBIQCgxFbWFpbEludmFsaWQQFBITCg9QYXNzd29yZEludmFsaWQQFRITCg9Vc2VyTmFtZUludmFsaWQQFhIYChRVc2VyV29ya3NwYWNlSW52YWxpZBAXEhEKDVVzZXJJZEludmFsaWQQGA=='); +final $typed_data.Uint8List userErrorCodeDescriptor = $convert.base64Decode('Cg1Vc2VyRXJyb3JDb2RlEgsKB1Vua25vd24QABIaChZVc2VyRGF0YWJhc2VJbml0RmFpbGVkEAESGwoXVXNlckRhdGFiYXNlV3JpdGVMb2NrZWQQAhIaChZVc2VyRGF0YWJhc2VSZWFkTG9ja2VkEAMSGwoXVXNlckRhdGFiYXNlRGlkTm90TWF0Y2gQBBIdChlVc2VyRGF0YWJhc2VJbnRlcm5hbEVycm9yEAUSEwoPVXNlck5vdExvZ2luWWV0EAoSFwoTUmVhZEN1cnJlbnRJZEZhaWxlZBALEhgKFFdyaXRlQ3VycmVudElkRmFpbGVkEAwSEAoMRW1haWxJbnZhbGlkEBQSEwoPUGFzc3dvcmRJbnZhbGlkEBUSEwoPVXNlck5hbWVJbnZhbGlkEBYSGAoUVXNlcldvcmtzcGFjZUludmFsaWQQFxIRCg1Vc2VySWRJbnZhbGlkEBgSIAocQ3JlYXRlRGVmYXVsdFdvcmtzcGFjZUZhaWxlZBAZ'); @$core.Deprecated('Use userErrorDescriptor instead') const UserError$json = const { '1': 'UserError', diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pb.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pb.dart index 7358eb7dca..fdb1ac1482 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pb.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pb.dart @@ -147,8 +147,8 @@ class ColorStyle extends $pb.GeneratedMessage { void clearThemeColor() => clearField(1); } -class AppDetail extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AppDetail', createEmptyInstance: create) +class App extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'App', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspaceId') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') @@ -156,8 +156,8 @@ class AppDetail extends $pb.GeneratedMessage { ..hasRequiredFields = false ; - AppDetail._() : super(); - factory AppDetail({ + App._() : super(); + factory App({ $core.String? id, $core.String? workspaceId, $core.String? name, @@ -178,26 +178,26 @@ class AppDetail extends $pb.GeneratedMessage { } return _result; } - factory AppDetail.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory AppDetail.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory App.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory App.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - AppDetail clone() => AppDetail()..mergeFromMessage(this); + App clone() => App()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - AppDetail copyWith(void Function(AppDetail) updates) => super.copyWith((message) => updates(message as AppDetail)) as AppDetail; // ignore: deprecated_member_use + App copyWith(void Function(App) updates) => super.copyWith((message) => updates(message as App)) as App; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static AppDetail create() => AppDetail._(); - AppDetail createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static App create() => App._(); + App createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static AppDetail getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static AppDetail? _defaultInstance; + static App getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static App? _defaultInstance; @$pb.TagNumber(1) $core.String get id => $_getSZ(0); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pbjson.dart index 3e2548d302..46e4b0b849 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pbjson.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/app_create.pbjson.dart @@ -31,9 +31,9 @@ const ColorStyle$json = const { /// Descriptor for `ColorStyle`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List colorStyleDescriptor = $convert.base64Decode('CgpDb2xvclN0eWxlEh8KC3RoZW1lX2NvbG9yGAEgASgJUgp0aGVtZUNvbG9y'); -@$core.Deprecated('Use appDetailDescriptor instead') -const AppDetail$json = const { - '1': 'AppDetail', +@$core.Deprecated('Use appDescriptor instead') +const App$json = const { + '1': 'App', '2': const [ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, const {'1': 'workspace_id', '3': 2, '4': 1, '5': 9, '10': 'workspaceId'}, @@ -42,5 +42,5 @@ const AppDetail$json = const { ], }; -/// Descriptor for `AppDetail`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List appDetailDescriptor = $convert.base64Decode('CglBcHBEZXRhaWwSDgoCaWQYASABKAlSAmlkEiEKDHdvcmtzcGFjZV9pZBgCIAEoCVILd29ya3NwYWNlSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNj'); +/// Descriptor for `App`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List appDescriptor = $convert.base64Decode('CgNBcHASDgoCaWQYASABKAlSAmlkEiEKDHdvcmtzcGFjZV9pZBgCIAEoCVILd29ya3NwYWNlSWQSEgoEbmFtZRgDIAEoCVIEbmFtZRISCgRkZXNjGAQgASgJUgRkZXNj'); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart index 37693a76d2..ede6d2aa55 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart @@ -14,10 +14,14 @@ class WorkspaceErrorCode extends $pb.ProtobufEnum { static const WorkspaceErrorCode WorkspaceNameInvalid = WorkspaceErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid'); static const WorkspaceErrorCode WorkspaceIdInvalid = WorkspaceErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid'); static const WorkspaceErrorCode AppColorStyleInvalid = WorkspaceErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid'); - static const WorkspaceErrorCode AppIdInvalid = WorkspaceErrorCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid'); - static const WorkspaceErrorCode DatabaseConnectionFail = WorkspaceErrorCode._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseConnectionFail'); - static const WorkspaceErrorCode DatabaseInternalError = WorkspaceErrorCode._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseInternalError'); - static const WorkspaceErrorCode UserInternalError = WorkspaceErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserInternalError'); + static const WorkspaceErrorCode AppIdInvalid = WorkspaceErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid'); + static const WorkspaceErrorCode AppNameInvalid = WorkspaceErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppNameInvalid'); + static const WorkspaceErrorCode ViewNameInvalid = WorkspaceErrorCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameInvalid'); + static const WorkspaceErrorCode ViewThumbnailName = WorkspaceErrorCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewThumbnailName'); + static const WorkspaceErrorCode DatabaseConnectionFail = WorkspaceErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseConnectionFail'); + static const WorkspaceErrorCode WorkspaceDatabaseError = WorkspaceErrorCode._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDatabaseError'); + static const WorkspaceErrorCode UserInternalError = WorkspaceErrorCode._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserInternalError'); + static const WorkspaceErrorCode UserNotLoginYet = WorkspaceErrorCode._(103, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotLoginYet'); static const $core.List values = [ Unknown, @@ -25,9 +29,13 @@ class WorkspaceErrorCode extends $pb.ProtobufEnum { WorkspaceIdInvalid, AppColorStyleInvalid, AppIdInvalid, + AppNameInvalid, + ViewNameInvalid, + ViewThumbnailName, DatabaseConnectionFail, - DatabaseInternalError, + WorkspaceDatabaseError, UserInternalError, + UserNotLoginYet, ]; static final $core.Map<$core.int, WorkspaceErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart index e2ce8025a2..1dd3186d24 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart @@ -16,15 +16,19 @@ const WorkspaceErrorCode$json = const { const {'1': 'WorkspaceNameInvalid', '2': 1}, const {'1': 'WorkspaceIdInvalid', '2': 2}, const {'1': 'AppColorStyleInvalid', '2': 3}, - const {'1': 'AppIdInvalid', '2': 4}, - const {'1': 'DatabaseConnectionFail', '2': 5}, - const {'1': 'DatabaseInternalError', '2': 6}, - const {'1': 'UserInternalError', '2': 10}, + const {'1': 'AppIdInvalid', '2': 10}, + const {'1': 'AppNameInvalid', '2': 11}, + const {'1': 'ViewNameInvalid', '2': 20}, + const {'1': 'ViewThumbnailName', '2': 21}, + const {'1': 'DatabaseConnectionFail', '2': 100}, + const {'1': 'WorkspaceDatabaseError', '2': 101}, + const {'1': 'UserInternalError', '2': 102}, + const {'1': 'UserNotLoginYet', '2': 103}, ], }; /// Descriptor for `WorkspaceErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List workspaceErrorCodeDescriptor = $convert.base64Decode('ChJXb3Jrc3BhY2VFcnJvckNvZGUSCwoHVW5rbm93bhAAEhgKFFdvcmtzcGFjZU5hbWVJbnZhbGlkEAESFgoSV29ya3NwYWNlSWRJbnZhbGlkEAISGAoUQXBwQ29sb3JTdHlsZUludmFsaWQQAxIQCgxBcHBJZEludmFsaWQQBBIaChZEYXRhYmFzZUNvbm5lY3Rpb25GYWlsEAUSGQoVRGF0YWJhc2VJbnRlcm5hbEVycm9yEAYSFQoRVXNlckludGVybmFsRXJyb3IQCg=='); +final $typed_data.Uint8List workspaceErrorCodeDescriptor = $convert.base64Decode('ChJXb3Jrc3BhY2VFcnJvckNvZGUSCwoHVW5rbm93bhAAEhgKFFdvcmtzcGFjZU5hbWVJbnZhbGlkEAESFgoSV29ya3NwYWNlSWRJbnZhbGlkEAISGAoUQXBwQ29sb3JTdHlsZUludmFsaWQQAxIQCgxBcHBJZEludmFsaWQQChISCg5BcHBOYW1lSW52YWxpZBALEhMKD1ZpZXdOYW1lSW52YWxpZBAUEhUKEVZpZXdUaHVtYm5haWxOYW1lEBUSGgoWRGF0YWJhc2VDb25uZWN0aW9uRmFpbBBkEhoKFldvcmtzcGFjZURhdGFiYXNlRXJyb3IQZRIVChFVc2VySW50ZXJuYWxFcnJvchBmEhMKD1VzZXJOb3RMb2dpbllldBBn'); @$core.Deprecated('Use workspaceErrorDescriptor instead') const WorkspaceError$json = const { '1': 'WorkspaceError', diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart index 343c57dc50..08cec09e19 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart @@ -11,9 +11,15 @@ import 'package:protobuf/protobuf.dart' as $pb; class WorkspaceEvent extends $pb.ProtobufEnum { static const WorkspaceEvent CreateWorkspace = WorkspaceEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateWorkspace'); + static const WorkspaceEvent GetWorkspaceDetail = WorkspaceEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetWorkspaceDetail'); + static const WorkspaceEvent CreateApp = WorkspaceEvent._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateApp'); + static const WorkspaceEvent CreateView = WorkspaceEvent._(201, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateView'); static const $core.List values = [ CreateWorkspace, + GetWorkspaceDetail, + CreateApp, + CreateView, ]; static final $core.Map<$core.int, WorkspaceEvent> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart index 5f2eac2e84..b7cdc7c7d0 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart @@ -13,8 +13,11 @@ const WorkspaceEvent$json = const { '1': 'WorkspaceEvent', '2': const [ const {'1': 'CreateWorkspace', '2': 0}, + const {'1': 'GetWorkspaceDetail', '2': 1}, + const {'1': 'CreateApp', '2': 101}, + const {'1': 'CreateView', '2': 201}, ], }; /// Descriptor for `WorkspaceEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQAA=='); +final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABIWChJHZXRXb3Jrc3BhY2VEZXRhaWwQARINCglDcmVhdGVBcHAQZRIPCgpDcmVhdGVWaWV3EMkB'); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart index c2b727a826..cf45ec07ad 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart @@ -3,5 +3,7 @@ export './errors.pb.dart'; export './workspace_update.pb.dart'; export './app_create.pb.dart'; export './event.pb.dart'; +export './view_create.pb.dart'; +export './workspace_user_detail.pb.dart'; export './workspace_create.pb.dart'; export './app_update.pb.dart'; diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pb.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pb.dart new file mode 100644 index 0000000000..82f7d3a17d --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pb.dart @@ -0,0 +1,234 @@ +/// +// Generated code. Do not modify. +// source: view_create.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'view_create.pbenum.dart'; + +export 'view_create.pbenum.dart'; + +enum CreateViewRequest_OneOfThumbnail { + thumbnail, + notSet +} + +class CreateViewRequest extends $pb.GeneratedMessage { + static const $core.Map<$core.int, CreateViewRequest_OneOfThumbnail> _CreateViewRequest_OneOfThumbnailByTag = { + 4 : CreateViewRequest_OneOfThumbnail.thumbnail, + 0 : CreateViewRequest_OneOfThumbnail.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateViewRequest', createEmptyInstance: create) + ..oo(0, [4]) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'appId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewTypeIdentifier.Docs, valueOf: ViewTypeIdentifier.valueOf, enumValues: ViewTypeIdentifier.values) + ..hasRequiredFields = false + ; + + CreateViewRequest._() : super(); + factory CreateViewRequest({ + $core.String? appId, + $core.String? name, + $core.String? desc, + $core.String? thumbnail, + ViewTypeIdentifier? viewType, + }) { + final _result = create(); + if (appId != null) { + _result.appId = appId; + } + if (name != null) { + _result.name = name; + } + if (desc != null) { + _result.desc = desc; + } + if (thumbnail != null) { + _result.thumbnail = thumbnail; + } + if (viewType != null) { + _result.viewType = viewType; + } + return _result; + } + factory CreateViewRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CreateViewRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + CreateViewRequest clone() => CreateViewRequest()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + CreateViewRequest copyWith(void Function(CreateViewRequest) updates) => super.copyWith((message) => updates(message as CreateViewRequest)) as CreateViewRequest; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CreateViewRequest create() => CreateViewRequest._(); + CreateViewRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static CreateViewRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static CreateViewRequest? _defaultInstance; + + CreateViewRequest_OneOfThumbnail whichOneOfThumbnail() => _CreateViewRequest_OneOfThumbnailByTag[$_whichOneof(0)]!; + void clearOneOfThumbnail() => clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $core.String get appId => $_getSZ(0); + @$pb.TagNumber(1) + set appId($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasAppId() => $_has(0); + @$pb.TagNumber(1) + void clearAppId() => clearField(1); + + @$pb.TagNumber(2) + $core.String get name => $_getSZ(1); + @$pb.TagNumber(2) + set name($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasName() => $_has(1); + @$pb.TagNumber(2) + void clearName() => clearField(2); + + @$pb.TagNumber(3) + $core.String get desc => $_getSZ(2); + @$pb.TagNumber(3) + set desc($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasDesc() => $_has(2); + @$pb.TagNumber(3) + void clearDesc() => clearField(3); + + @$pb.TagNumber(4) + $core.String get thumbnail => $_getSZ(3); + @$pb.TagNumber(4) + set thumbnail($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasThumbnail() => $_has(3); + @$pb.TagNumber(4) + void clearThumbnail() => clearField(4); + + @$pb.TagNumber(5) + ViewTypeIdentifier get viewType => $_getN(4); + @$pb.TagNumber(5) + set viewType(ViewTypeIdentifier v) { setField(5, v); } + @$pb.TagNumber(5) + $core.bool hasViewType() => $_has(4); + @$pb.TagNumber(5) + void clearViewType() => clearField(5); +} + +class View extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'View', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'appId') + ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') + ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewTypeIdentifier.Docs, valueOf: ViewTypeIdentifier.valueOf, enumValues: ViewTypeIdentifier.values) + ..hasRequiredFields = false + ; + + View._() : super(); + factory View({ + $core.String? id, + $core.String? appId, + $core.String? name, + $core.String? desc, + ViewTypeIdentifier? viewType, + }) { + final _result = create(); + if (id != null) { + _result.id = id; + } + if (appId != null) { + _result.appId = appId; + } + if (name != null) { + _result.name = name; + } + if (desc != null) { + _result.desc = desc; + } + if (viewType != null) { + _result.viewType = viewType; + } + return _result; + } + factory View.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory View.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + View clone() => View()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + View copyWith(void Function(View) updates) => super.copyWith((message) => updates(message as View)) as View; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static View create() => View._(); + View createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static View getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static View? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get id => $_getSZ(0); + @$pb.TagNumber(1) + set id($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => clearField(1); + + @$pb.TagNumber(2) + $core.String get appId => $_getSZ(1); + @$pb.TagNumber(2) + set appId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasAppId() => $_has(1); + @$pb.TagNumber(2) + void clearAppId() => clearField(2); + + @$pb.TagNumber(3) + $core.String get name => $_getSZ(2); + @$pb.TagNumber(3) + set name($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasName() => $_has(2); + @$pb.TagNumber(3) + void clearName() => clearField(3); + + @$pb.TagNumber(4) + $core.String get desc => $_getSZ(3); + @$pb.TagNumber(4) + set desc($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasDesc() => $_has(3); + @$pb.TagNumber(4) + void clearDesc() => clearField(4); + + @$pb.TagNumber(5) + ViewTypeIdentifier get viewType => $_getN(4); + @$pb.TagNumber(5) + set viewType(ViewTypeIdentifier v) { setField(5, v); } + @$pb.TagNumber(5) + $core.bool hasViewType() => $_has(4); + @$pb.TagNumber(5) + void clearViewType() => clearField(5); +} + diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbenum.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbenum.dart new file mode 100644 index 0000000000..a685816a29 --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbenum.dart @@ -0,0 +1,24 @@ +/// +// Generated code. Do not modify. +// source: view_create.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +// ignore_for_file: UNDEFINED_SHOWN_NAME +import 'dart:core' as $core; +import 'package:protobuf/protobuf.dart' as $pb; + +class ViewTypeIdentifier extends $pb.ProtobufEnum { + static const ViewTypeIdentifier Docs = ViewTypeIdentifier._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Docs'); + + static const $core.List values = [ + Docs, + ]; + + static final $core.Map<$core.int, ViewTypeIdentifier> _byValue = $pb.ProtobufEnum.initByValue(values); + static ViewTypeIdentifier? valueOf($core.int value) => _byValue[value]; + + const ViewTypeIdentifier._($core.int v, $core.String n) : super(v, n); +} + diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbjson.dart new file mode 100644 index 0000000000..c17dd1699e --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbjson.dart @@ -0,0 +1,51 @@ +/// +// Generated code. Do not modify. +// source: view_create.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use viewTypeIdentifierDescriptor instead') +const ViewTypeIdentifier$json = const { + '1': 'ViewTypeIdentifier', + '2': const [ + const {'1': 'Docs', '2': 0}, + ], +}; + +/// Descriptor for `ViewTypeIdentifier`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List viewTypeIdentifierDescriptor = $convert.base64Decode('ChJWaWV3VHlwZUlkZW50aWZpZXISCAoERG9jcxAA'); +@$core.Deprecated('Use createViewRequestDescriptor instead') +const CreateViewRequest$json = const { + '1': 'CreateViewRequest', + '2': const [ + const {'1': 'app_id', '3': 1, '4': 1, '5': 9, '10': 'appId'}, + const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, + const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'}, + const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'thumbnail'}, + const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewTypeIdentifier', '10': 'viewType'}, + ], + '8': const [ + const {'1': 'one_of_thumbnail'}, + ], +}; + +/// Descriptor for `CreateViewRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List createViewRequestDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UmVxdWVzdBIVCgZhcHBfaWQYASABKAlSBWFwcElkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIeCgl0aHVtYm5haWwYBCABKAlIAFIJdGh1bWJuYWlsEjAKCXZpZXdfdHlwZRgFIAEoDjITLlZpZXdUeXBlSWRlbnRpZmllclIIdmlld1R5cGVCEgoQb25lX29mX3RodW1ibmFpbA=='); +@$core.Deprecated('Use viewDescriptor instead') +const View$json = const { + '1': 'View', + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + const {'1': 'app_id', '3': 2, '4': 1, '5': 9, '10': 'appId'}, + const {'1': 'name', '3': 3, '4': 1, '5': 9, '10': 'name'}, + const {'1': 'desc', '3': 4, '4': 1, '5': 9, '10': 'desc'}, + const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewTypeIdentifier', '10': 'viewType'}, + ], +}; + +/// Descriptor for `View`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List viewDescriptor = $convert.base64Decode('CgRWaWV3Eg4KAmlkGAEgASgJUgJpZBIVCgZhcHBfaWQYAiABKAlSBWFwcElkEhIKBG5hbWUYAyABKAlSBG5hbWUSEgoEZGVzYxgEIAEoCVIEZGVzYxIwCgl2aWV3X3R5cGUYBSABKA4yEy5WaWV3VHlwZUlkZW50aWZpZXJSCHZpZXdUeXBl'); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbserver.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbserver.dart new file mode 100644 index 0000000000..8bfbe9d7d2 --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/view_create.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: view_create.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +export 'view_create.pb.dart'; + diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pb.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pb.dart index 7b2f9bf8d7..e14b1f4382 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pb.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pb.dart @@ -70,16 +70,16 @@ class CreateWorkspaceRequest extends $pb.GeneratedMessage { void clearDesc() => clearField(2); } -class WorkspaceDetail extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WorkspaceDetail', createEmptyInstance: create) +class Workspace extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Workspace', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name') ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') ..hasRequiredFields = false ; - WorkspaceDetail._() : super(); - factory WorkspaceDetail({ + Workspace._() : super(); + factory Workspace({ $core.String? id, $core.String? name, $core.String? desc, @@ -96,26 +96,26 @@ class WorkspaceDetail extends $pb.GeneratedMessage { } return _result; } - factory WorkspaceDetail.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WorkspaceDetail.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory Workspace.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Workspace.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - WorkspaceDetail clone() => WorkspaceDetail()..mergeFromMessage(this); + Workspace clone() => Workspace()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - WorkspaceDetail copyWith(void Function(WorkspaceDetail) updates) => super.copyWith((message) => updates(message as WorkspaceDetail)) as WorkspaceDetail; // ignore: deprecated_member_use + Workspace copyWith(void Function(Workspace) updates) => super.copyWith((message) => updates(message as Workspace)) as Workspace; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static WorkspaceDetail create() => WorkspaceDetail._(); - WorkspaceDetail createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static Workspace create() => Workspace._(); + Workspace createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static WorkspaceDetail getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static WorkspaceDetail? _defaultInstance; + static Workspace getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Workspace? _defaultInstance; @$pb.TagNumber(1) $core.String get id => $_getSZ(0); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pbjson.dart index fcdf6d0c55..89729f1fc4 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pbjson.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_create.pbjson.dart @@ -19,9 +19,9 @@ const CreateWorkspaceRequest$json = const { /// Descriptor for `CreateWorkspaceRequest`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List createWorkspaceRequestDescriptor = $convert.base64Decode('ChZDcmVhdGVXb3Jrc3BhY2VSZXF1ZXN0EhIKBG5hbWUYASABKAlSBG5hbWUSEgoEZGVzYxgCIAEoCVIEZGVzYw=='); -@$core.Deprecated('Use workspaceDetailDescriptor instead') -const WorkspaceDetail$json = const { - '1': 'WorkspaceDetail', +@$core.Deprecated('Use workspaceDescriptor instead') +const Workspace$json = const { + '1': 'Workspace', '2': const [ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, const {'1': 'name', '3': 2, '4': 1, '5': 9, '10': 'name'}, @@ -29,5 +29,5 @@ const WorkspaceDetail$json = const { ], }; -/// Descriptor for `WorkspaceDetail`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List workspaceDetailDescriptor = $convert.base64Decode('Cg9Xb3Jrc3BhY2VEZXRhaWwSDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYw=='); +/// Descriptor for `Workspace`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List workspaceDescriptor = $convert.base64Decode('CglXb3Jrc3BhY2USDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYw=='); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pb.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pb.dart new file mode 100644 index 0000000000..553d431dd9 --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pb.dart @@ -0,0 +1,137 @@ +/// +// Generated code. Do not modify. +// source: workspace_user_detail.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'workspace_create.pb.dart' as $0; + +class UserWorkspace extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserWorkspace', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'owner') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspaceId') + ..hasRequiredFields = false + ; + + UserWorkspace._() : super(); + factory UserWorkspace({ + $core.String? owner, + $core.String? workspaceId, + }) { + final _result = create(); + if (owner != null) { + _result.owner = owner; + } + if (workspaceId != null) { + _result.workspaceId = workspaceId; + } + return _result; + } + factory UserWorkspace.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory UserWorkspace.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + UserWorkspace clone() => UserWorkspace()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + UserWorkspace copyWith(void Function(UserWorkspace) updates) => super.copyWith((message) => updates(message as UserWorkspace)) as UserWorkspace; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static UserWorkspace create() => UserWorkspace._(); + UserWorkspace createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static UserWorkspace getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static UserWorkspace? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get owner => $_getSZ(0); + @$pb.TagNumber(1) + set owner($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasOwner() => $_has(0); + @$pb.TagNumber(1) + void clearOwner() => clearField(1); + + @$pb.TagNumber(2) + $core.String get workspaceId => $_getSZ(1); + @$pb.TagNumber(2) + set workspaceId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasWorkspaceId() => $_has(1); + @$pb.TagNumber(2) + void clearWorkspaceId() => clearField(2); +} + +class UserWorkspaceDetail extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserWorkspaceDetail', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'owner') + ..aOM<$0.Workspace>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'workspace', subBuilder: $0.Workspace.create) + ..hasRequiredFields = false + ; + + UserWorkspaceDetail._() : super(); + factory UserWorkspaceDetail({ + $core.String? owner, + $0.Workspace? workspace, + }) { + final _result = create(); + if (owner != null) { + _result.owner = owner; + } + if (workspace != null) { + _result.workspace = workspace; + } + return _result; + } + factory UserWorkspaceDetail.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory UserWorkspaceDetail.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + UserWorkspaceDetail clone() => UserWorkspaceDetail()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + UserWorkspaceDetail copyWith(void Function(UserWorkspaceDetail) updates) => super.copyWith((message) => updates(message as UserWorkspaceDetail)) as UserWorkspaceDetail; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static UserWorkspaceDetail create() => UserWorkspaceDetail._(); + UserWorkspaceDetail createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static UserWorkspaceDetail getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static UserWorkspaceDetail? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get owner => $_getSZ(0); + @$pb.TagNumber(1) + set owner($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasOwner() => $_has(0); + @$pb.TagNumber(1) + void clearOwner() => clearField(1); + + @$pb.TagNumber(2) + $0.Workspace get workspace => $_getN(1); + @$pb.TagNumber(2) + set workspace($0.Workspace v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasWorkspace() => $_has(1); + @$pb.TagNumber(2) + void clearWorkspace() => clearField(2); + @$pb.TagNumber(2) + $0.Workspace ensureWorkspace() => $_ensure(1); +} + diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbenum.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbenum.dart new file mode 100644 index 0000000000..ca5e23ef81 --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbenum.dart @@ -0,0 +1,7 @@ +/// +// Generated code. Do not modify. +// source: workspace_user_detail.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbjson.dart new file mode 100644 index 0000000000..b267e42d5b --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbjson.dart @@ -0,0 +1,32 @@ +/// +// Generated code. Do not modify. +// source: workspace_user_detail.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use userWorkspaceDescriptor instead') +const UserWorkspace$json = const { + '1': 'UserWorkspace', + '2': const [ + const {'1': 'owner', '3': 1, '4': 1, '5': 9, '10': 'owner'}, + const {'1': 'workspace_id', '3': 2, '4': 1, '5': 9, '10': 'workspaceId'}, + ], +}; + +/// Descriptor for `UserWorkspace`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List userWorkspaceDescriptor = $convert.base64Decode('Cg1Vc2VyV29ya3NwYWNlEhQKBW93bmVyGAEgASgJUgVvd25lchIhCgx3b3Jrc3BhY2VfaWQYAiABKAlSC3dvcmtzcGFjZUlk'); +@$core.Deprecated('Use userWorkspaceDetailDescriptor instead') +const UserWorkspaceDetail$json = const { + '1': 'UserWorkspaceDetail', + '2': const [ + const {'1': 'owner', '3': 1, '4': 1, '5': 9, '10': 'owner'}, + const {'1': 'workspace', '3': 2, '4': 1, '5': 11, '6': '.Workspace', '10': 'workspace'}, + ], +}; + +/// Descriptor for `UserWorkspaceDetail`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List userWorkspaceDetailDescriptor = $convert.base64Decode('ChNVc2VyV29ya3NwYWNlRGV0YWlsEhQKBW93bmVyGAEgASgJUgVvd25lchIoCgl3b3Jrc3BhY2UYAiABKAsyCi5Xb3Jrc3BhY2VSCXdvcmtzcGFjZQ=='); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbserver.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbserver.dart new file mode 100644 index 0000000000..8fc33d92ca --- /dev/null +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/workspace_user_detail.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: workspace_user_detail.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +export 'workspace_user_detail.pb.dart'; + diff --git a/app_flowy/pubspec.lock b/app_flowy/pubspec.lock index f8627b337e..58a8783ca8 100644 --- a/app_flowy/pubspec.lock +++ b/app_flowy/pubspec.lock @@ -253,6 +253,20 @@ packages: relative: true source: path version: "0.0.1" + flowy_infra_ui_platform_interface: + dependency: transitive + description: + path: "packages/flowy_infra_ui/flowy_infra_ui_platform_interface" + relative: true + source: path + version: "0.0.1" + flowy_infra_ui_web: + dependency: transitive + description: + path: "packages/flowy_infra_ui/flowy_infra_ui_web" + relative: true + source: path + version: "0.0.1" flowy_sdk: dependency: "direct main" description: diff --git a/rust-lib/.gitignore b/rust-lib/.gitignore index e2b01170f3..a42aa3663e 100644 --- a/rust-lib/.gitignore +++ b/rust-lib/.gitignore @@ -10,4 +10,6 @@ Cargo.lock **/*.rs.bk **/**/*.log* **/**/temp -bin/ \ No newline at end of file +bin/ + +.idea/ \ No newline at end of file diff --git a/rust-lib/.idea/.gitignore b/rust-lib/.idea/.gitignore deleted file mode 100644 index 73f69e0958..0000000000 --- a/rust-lib/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/rust-lib/.idea/modules.xml b/rust-lib/.idea/modules.xml deleted file mode 100644 index 332e83b7bd..0000000000 --- a/rust-lib/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/rust-lib/.idea/rust-lib.iml b/rust-lib/.idea/rust-lib.iml deleted file mode 100644 index 257d037616..0000000000 --- a/rust-lib/.idea/rust-lib.iml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rust-lib/.idea/vcs.xml b/rust-lib/.idea/vcs.xml deleted file mode 100644 index 6c0b863585..0000000000 --- a/rust-lib/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/rust-lib/dart-ffi/src/lib.rs b/rust-lib/dart-ffi/src/lib.rs index 9a04592458..5c7f0b28c0 100644 --- a/rust-lib/dart-ffi/src/lib.rs +++ b/rust-lib/dart-ffi/src/lib.rs @@ -40,7 +40,7 @@ pub extern "C" fn async_command(port: i64, input: *const u8, len: usize) { port ); - let _ = EventDispatch::async_send(request, move |resp: EventResponse| { + let _ = EventDispatch::async_send_with_callback(request, move |resp: EventResponse| { log::trace!("[FFI]: Post data to dart through {} port", port); Box::pin(post_to_flutter(resp, port)) }); diff --git a/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/down.sql b/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/down.sql index f1119aa25a..77ba5442e2 100644 --- a/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/down.sql +++ b/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/down.sql @@ -1,2 +1,5 @@ -- This file should undo anything in `up.sql` -DROP TABLE user_table; \ No newline at end of file +DROP TABLE user_table; +DROP TABLE workspace_table; +DROP TABLE app_table; +DROP TABLE view_table; \ No newline at end of file diff --git a/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql b/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql index 2ea0349782..570b6c4e4b 100644 --- a/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql +++ b/rust-lib/flowy-database/migrations/2021-07-09-063045_flowy-user/up.sql @@ -6,3 +6,37 @@ CREATE TABLE user_table ( password TEXT NOT NULL DEFAULT '', email TEXT NOT NULL DEFAULT '' ); + +CREATE TABLE workspace_table ( + id TEXT NOT NULL PRIMARY KEY, + name TEXT NOT NULL DEFAULT '', + desc TEXT NOT NULL DEFAULT '', + modified_time BIGINT NOT NULL DEFAULT 0, + create_time BIGINT NOT NULL DEFAULT 0, + user_id TEXT NOT NULL DEFAULT '', + version BIGINT NOT NULL DEFAULT 0 +); + +CREATE TABLE app_table ( + id TEXT NOT NULL PRIMARY KEY, + workspace_id TEXT NOT NULL DEFAULT '', + name TEXT NOT NULL DEFAULT '', + desc TEXT NOT NULL DEFAULT '', + color_style BLOB NOT NULL DEFAULT (x''), + last_view_id TEXT DEFAULT '', + modified_time BIGINT NOT NULL DEFAULT 0, + create_time BIGINT NOT NULL DEFAULT 0, + version BIGINT NOT NULL DEFAULT 0 +); + +CREATE TABLE view_table ( + id TEXT NOT NULL PRIMARY KEY, + app_id TEXT NOT NULL DEFAULT '', + name TEXT NOT NULL DEFAULT '', + desc TEXT NOT NULL DEFAULT '', + modified_time BIGINT NOT NULL DEFAULT 0, + create_time BIGINT NOT NULL DEFAULT 0, + thumbnail TEXT NOT NULL DEFAULT '', + view_type INTEGER NOT NULL DEFAULT 0, + version BIGINT NOT NULL DEFAULT 0 +); diff --git a/rust-lib/flowy-database/migrations/2021-07-13-063102_flowy-workspace/down.sql b/rust-lib/flowy-database/migrations/2021-07-13-063102_flowy-workspace/down.sql deleted file mode 100644 index bacfe9a64b..0000000000 --- a/rust-lib/flowy-database/migrations/2021-07-13-063102_flowy-workspace/down.sql +++ /dev/null @@ -1,4 +0,0 @@ --- This file should undo anything in `up.sql` -DROP TABLE workspace_table; -DROP TABLE app_table; -DROP TABLE view_table; \ No newline at end of file diff --git a/rust-lib/flowy-database/migrations/2021-07-13-063102_flowy-workspace/up.sql b/rust-lib/flowy-database/migrations/2021-07-13-063102_flowy-workspace/up.sql deleted file mode 100644 index 334b920141..0000000000 --- a/rust-lib/flowy-database/migrations/2021-07-13-063102_flowy-workspace/up.sql +++ /dev/null @@ -1,34 +0,0 @@ --- Your SQL goes here -CREATE TABLE workspace_table ( - id TEXT NOT NULL PRIMARY KEY, - name TEXT NOT NULL DEFAULT '', - desc TEXT NOT NULL DEFAULT '', - modified_time BIGINT NOT NULL DEFAULT 0, - create_time BIGINT NOT NULL DEFAULT 0, - user_id TEXT NOT NULL DEFAULT '', - version BIGINT NOT NULL DEFAULT 0 -); - -CREATE TABLE app_table ( - id TEXT NOT NULL PRIMARY KEY, - workspace_id TEXT NOT NULL DEFAULT '', - name TEXT NOT NULL DEFAULT '', - desc TEXT NOT NULL DEFAULT '', - color_style BLOB NOT NULL DEFAULT (x''), - last_view_id TEXT DEFAULT '', - modified_time BIGINT NOT NULL DEFAULT 0, - create_time BIGINT NOT NULL DEFAULT 0, - version BIGINT NOT NULL DEFAULT 0 -); - -CREATE TABLE view_table ( - id TEXT NOT NULL PRIMARY KEY, - app_id TEXT NOT NULL DEFAULT '', - name TEXT NOT NULL DEFAULT '', - desc TEXT NOT NULL DEFAULT '', - modified_time BIGINT NOT NULL DEFAULT 0, - create_time BIGINT NOT NULL DEFAULT 0, - thumbnail TEXT NOT NULL DEFAULT '', - view_type INTEGER NOT NULL DEFAULT 0, - version BIGINT NOT NULL DEFAULT 0 -); diff --git a/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs b/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs index c0efa13115..f9ff418873 100644 --- a/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -18,11 +18,15 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { "KeyValue" | "CreateAppRequest" | "ColorStyle" - | "AppDetail" + | "App" | "UpdateAppRequest" | "UpdateWorkspaceRequest" | "CreateWorkspaceRequest" - | "WorkspaceDetail" + | "Workspace" + | "UserWorkspace" + | "UserWorkspaceDetail" + | "CreateViewRequest" + | "View" | "WorkspaceError" | "FFIRequest" | "FFIResponse" @@ -35,7 +39,8 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "SignInParams" | "UserError" => TypeCategory::Protobuf, - "WorkspaceEvent" + "ViewTypeIdentifier" + | "WorkspaceEvent" | "WorkspaceErrorCode" | "FFIStatusCode" | "UserStatus" diff --git a/rust-lib/flowy-derive/tests/progress.rs b/rust-lib/flowy-derive/tests/progress.rs index 6f1f5b1b9e..c4380d6778 100644 --- a/rust-lib/flowy-derive/tests/progress.rs +++ b/rust-lib/flowy-derive/tests/progress.rs @@ -1,5 +1,5 @@ #[tokio::test] async fn tests() { - let t = trybuild::TestCases::new(); + let _t = trybuild::TestCases::new(); // t.pass("tests/protobuf_enum.rs"); } diff --git a/rust-lib/flowy-dispatch/src/dispatch.rs b/rust-lib/flowy-dispatch/src/dispatch.rs index d2cc1a58bf..aac9c410a7 100644 --- a/rust-lib/flowy-dispatch/src/dispatch.rs +++ b/rust-lib/flowy-dispatch/src/dispatch.rs @@ -38,7 +38,17 @@ impl EventDispatch { *(EVENT_DISPATCH.write().unwrap()) = Some(dispatch); } - pub fn async_send(request: Req, callback: Callback) -> DispatchFuture + pub fn async_send(request: Req) -> DispatchFuture + where + Req: std::convert::Into, + { + EventDispatch::async_send_with_callback(request, |_| Box::pin(async {})) + } + + pub fn async_send_with_callback( + request: Req, + callback: Callback, + ) -> DispatchFuture where Req: std::convert::Into, Callback: FnOnce(EventResponse) -> BoxFuture<'static, ()> + 'static + Send + Sync, @@ -83,19 +93,22 @@ impl EventDispatch { pub fn sync_send(request: ModuleRequest) -> EventResponse { futures::executor::block_on(async { - EventDispatch::async_send(request, |_| Box::pin(async {})).await + EventDispatch::async_send_with_callback(request, |_| Box::pin(async {})).await }) } } #[pin_project] -pub struct DispatchFuture { +pub struct DispatchFuture { #[pin] - fut: BoxFuture<'static, EventResponse>, + pub fut: Pin + Sync + Send>>, } -impl Future for DispatchFuture { - type Output = EventResponse; +impl Future for DispatchFuture +where + T: Send + Sync, +{ + type Output = T; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.as_mut().project(); diff --git a/rust-lib/flowy-dispatch/src/lib.rs b/rust-lib/flowy-dispatch/src/lib.rs index 744f7abc0e..5e0da9ac9a 100644 --- a/rust-lib/flowy-dispatch/src/lib.rs +++ b/rust-lib/flowy-dispatch/src/lib.rs @@ -12,6 +12,9 @@ mod data; mod dispatch; mod system; +#[macro_use] +pub mod macros; + pub use errors::Error; pub mod prelude { diff --git a/rust-lib/flowy-dispatch/src/macros.rs b/rust-lib/flowy-dispatch/src/macros.rs new file mode 100644 index 0000000000..c8fb5eb832 --- /dev/null +++ b/rust-lib/flowy-dispatch/src/macros.rs @@ -0,0 +1,8 @@ +#[macro_export] +macro_rules! dispatch_future { + ($fut:expr) => { + DispatchFuture { + fut: Box::pin(async move { $fut.await }), + } + }; +} diff --git a/rust-lib/flowy-dispatch/src/request/payload.rs b/rust-lib/flowy-dispatch/src/request/payload.rs index 049d1d93e8..374d3af999 100644 --- a/rust-lib/flowy-dispatch/src/request/payload.rs +++ b/rust-lib/flowy-dispatch/src/request/payload.rs @@ -48,16 +48,6 @@ impl std::convert::Into for Vec { fn into(self) -> Payload { Payload::Bytes(self) } } -// = note: conflicting implementation in crate `core`: -// - impl TryInto for T where U: TryFrom; -// -// impl std::convert::TryInto for Vec { -// type Error = String; -// fn try_into(self) -> Result { -// Ok(Payload::Bytes(self)) -// } -// } - impl std::convert::Into for &str { fn into(self) -> Payload { self.to_string().into() } } diff --git a/rust-lib/flowy-dispatch/tests/api/module.rs b/rust-lib/flowy-dispatch/tests/api/module.rs index be6b98ef64..65d1b12a52 100644 --- a/rust-lib/flowy-dispatch/tests/api/module.rs +++ b/rust-lib/flowy-dispatch/tests/api/module.rs @@ -10,7 +10,7 @@ async fn test_init() { init_dispatch(|| vec![Module::new().event(event, hello)]); let request = ModuleRequest::new(event); - let _ = EventDispatch::async_send(request, |resp| { + let _ = EventDispatch::async_send_with_callback(request, |resp| { Box::pin(async move { dbg!(&resp); }) diff --git a/rust-lib/flowy-infra/src/kv/kv.rs b/rust-lib/flowy-infra/src/kv/kv.rs index cadc0032b8..36bc30ecc1 100644 --- a/rust-lib/flowy-infra/src/kv/kv.rs +++ b/rust-lib/flowy-infra/src/kv/kv.rs @@ -18,22 +18,21 @@ pub struct KVStore { impl KVStore { fn new() -> Self { KVStore { database: None } } - pub fn set(item: KeyValue) -> Result<(), String> { - let conn = get_connection()?; + fn set(item: KeyValue) -> Result<(), String> { let _ = diesel::replace_into(kv_table::table) .values(&item) - .execute(&*conn) - .map_err(|e| format!("{:?}", e))?; + .execute(&*(get_connection()?)) + .map_err(|e| format!("KV set error: {:?}", e))?; Ok(()) } - pub fn get(key: &str) -> Result { + fn get(key: &str) -> Result { let conn = get_connection()?; let item = dsl::kv_table .filter(kv_table::key.eq(key)) .first::(&*conn) - .map_err(|e| format!("{:?}", e))?; + .map_err(|e| format!("KV get error: {:?}", e))?; Ok(item) } @@ -43,7 +42,7 @@ impl KVStore { let sql = dsl::kv_table.filter(kv_table::key.eq(key)); let _ = diesel::delete(sql) .execute(&*conn) - .map_err(|e| format!("{:?}", e))?; + .map_err(|e| format!("KV remove error: {:?}", e))?; Ok(()) } @@ -125,7 +124,7 @@ fn get_connection() -> Result { .as_ref() .expect("KVStore is not init") .get_connection() - .map_err(|e| format!("{:?}", e))?; + .map_err(|e| format!("KVStore error: {:?}", e))?; Ok(conn) }, Err(e) => { diff --git a/rust-lib/flowy-sdk/Cargo.toml b/rust-lib/flowy-sdk/Cargo.toml index 9be05f9cf8..6150dd01a3 100644 --- a/rust-lib/flowy-sdk/Cargo.toml +++ b/rust-lib/flowy-sdk/Cargo.toml @@ -15,6 +15,7 @@ flowy-workspace = { path = "../flowy-workspace" } flowy-database = { path = "../flowy-database" } tracing = { version = "0.1" } log = "0.4.14" +futures-core = { version = "0.3", default-features = false } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/rust-lib/flowy-sdk/src/deps_resolve/mod.rs b/rust-lib/flowy-sdk/src/deps_resolve/mod.rs new file mode 100644 index 0000000000..a49be3ee06 --- /dev/null +++ b/rust-lib/flowy-sdk/src/deps_resolve/mod.rs @@ -0,0 +1,3 @@ +mod workspace_user_impl; + +pub use workspace_user_impl::*; diff --git a/rust-lib/flowy-sdk/src/deps_resolve/workspace_user_impl.rs b/rust-lib/flowy-sdk/src/deps_resolve/workspace_user_impl.rs new file mode 100644 index 0000000000..df069a33a5 --- /dev/null +++ b/rust-lib/flowy-sdk/src/deps_resolve/workspace_user_impl.rs @@ -0,0 +1,63 @@ +use flowy_database::DBConnection; +use flowy_dispatch::prelude::DispatchFuture; +use flowy_user::prelude::UserSession; +use flowy_workspace::{ + entities::workspace::UserWorkspace, + errors::{ErrorBuilder, WorkspaceError, WorkspaceErrorCode}, + module::WorkspaceUser, +}; +use std::sync::Arc; + +pub struct WorkspaceUserImpl { + pub(crate) user_session: Arc, +} + +impl WorkspaceUser for WorkspaceUserImpl { + fn set_cur_workspace_id( + &self, + workspace_id: &str, + ) -> DispatchFuture> { + let user_session = self.user_session.clone(); + let workspace_id = workspace_id.to_owned(); + DispatchFuture { + fut: Box::pin(async move { + let _ = user_session + .set_current_workspace(&workspace_id) + .await + .map_err(|e| { + ErrorBuilder::new(WorkspaceErrorCode::UserInternalError) + .error(e) + .build() + }); + + Ok(()) + }), + } + } + + fn get_cur_workspace(&self) -> DispatchFuture> { + let user_session = self.user_session.clone(); + DispatchFuture { + fut: Box::pin(async move { + let user_detail = user_session.user_detail().map_err(|e| { + ErrorBuilder::new(WorkspaceErrorCode::UserNotLoginYet) + .error(e) + .build() + })?; + + Ok(UserWorkspace { + owner: user_detail.email, + workspace_id: user_detail.workspace, + }) + }), + } + } + + fn db_connection(&self) -> Result { + self.user_session.get_db_connection().map_err(|e| { + ErrorBuilder::new(WorkspaceErrorCode::DatabaseConnectionFail) + .error(e) + .build() + }) + } +} diff --git a/rust-lib/flowy-sdk/src/flowy_server.rs b/rust-lib/flowy-sdk/src/flowy_server.rs index 1ca319b6b9..08d5a8ea84 100644 --- a/rust-lib/flowy-sdk/src/flowy_server.rs +++ b/rust-lib/flowy-sdk/src/flowy_server.rs @@ -1,24 +1,28 @@ -use flowy_infra::uuid; +use flowy_dispatch::prelude::{DispatchFuture, EventDispatch, ModuleRequest, ToBytes}; use flowy_user::{ entities::{SignInParams, SignUpParams, UserDetail}, errors::{ErrorBuilder, UserError, UserErrorCode}, prelude::UserServer, - sql_tables::User, + sql_tables::UserTable, +}; +use flowy_workspace::{ + entities::workspace::{CreateWorkspaceRequest, Workspace}, + errors::WorkspaceError, + event::WorkspaceEvent::CreateWorkspace, }; pub type ArcFlowyServer = std::sync::Arc; pub trait FlowyServer: UserServer {} -pub struct MockFlowyServer {} +pub struct FlowyServerMocker {} -impl FlowyServer for MockFlowyServer {} +impl FlowyServer for FlowyServerMocker {} -impl UserServer for MockFlowyServer { - fn sign_up(&self, params: SignUpParams) -> Result { - // let user_id = "9527".to_owned(); - let user_id = uuid(); - Ok(User::new( +impl UserServer for FlowyServerMocker { + fn sign_up(&self, params: SignUpParams) -> Result { + let user_id = params.email.clone(); + Ok(UserTable::new( user_id, params.name, params.email, @@ -26,9 +30,9 @@ impl UserServer for MockFlowyServer { )) } - fn sign_in(&self, params: SignInParams) -> Result { - let user_id = uuid(); - Ok(User::new( + fn sign_in(&self, params: SignInParams) -> Result { + let user_id = params.email.clone(); + Ok(UserTable::new( user_id, "".to_owned(), params.email, @@ -36,11 +40,40 @@ impl UserServer for MockFlowyServer { )) } + fn sign_out(&self, _user_id: &str) -> Result<(), UserError> { + Err(ErrorBuilder::new(UserErrorCode::Unknown).build()) + } + fn get_user_info(&self, _user_id: &str) -> Result { Err(ErrorBuilder::new(UserErrorCode::Unknown).build()) } - fn sign_out(&self, _user_id: &str) -> Result<(), UserError> { - Err(ErrorBuilder::new(UserErrorCode::Unknown).build()) + fn create_workspace( + &self, + name: &str, + desc: &str, + _user_id: &str, + ) -> DispatchFuture> { + let payload: Vec = CreateWorkspaceRequest { + name: name.to_string(), + desc: desc.to_string(), + } + .into_bytes() + .unwrap(); + + let request = ModuleRequest::new(CreateWorkspace).payload(payload); + DispatchFuture { + fut: Box::pin(async move { + let _ = EventDispatch::async_send(request) + .await + .parse::() + .map_err(|e| { + ErrorBuilder::new(UserErrorCode::CreateDefaultWorkspaceFailed) + .error(e) + .build() + })?; + Ok(()) + }), + } } } diff --git a/rust-lib/flowy-sdk/src/lib.rs b/rust-lib/flowy-sdk/src/lib.rs index db7265177e..581b20d05e 100644 --- a/rust-lib/flowy-sdk/src/lib.rs +++ b/rust-lib/flowy-sdk/src/lib.rs @@ -1,7 +1,8 @@ +mod deps_resolve; mod flowy_server; pub mod module; -use crate::flowy_server::{ArcFlowyServer, MockFlowyServer}; +pub use crate::flowy_server::{ArcFlowyServer, FlowyServerMocker}; use flowy_dispatch::prelude::*; use module::build_modules; pub use module::*; @@ -18,19 +19,24 @@ pub struct FlowySDK { impl FlowySDK { pub fn new(root: &str) -> Self { - let server = Arc::new(MockFlowyServer {}); + let server = Arc::new(FlowyServerMocker {}); Self { root: root.to_owned(), server, } } - pub fn construct(self) { - FlowySDK::init_log(&self.root); + pub fn construct(self) { FlowySDK::construct_with(&self.root, self.server.clone()) } - tracing::info!("🔥 Root path: {}", self.root); - flowy_infra::kv::KVStore::init(&self.root); - FlowySDK::init_modules(&self.root, self.server); + pub fn construct_with(root: &str, server: ArcFlowyServer) { + FlowySDK::init_log(root); + + tracing::info!("🔥 Root path: {}", root); + match flowy_infra::kv::KVStore::init(root) { + Ok(_) => {}, + Err(e) => tracing::error!("Init kv store failedL: {}", e), + } + FlowySDK::init_modules(root, server); } fn init_log(directory: &str) { diff --git a/rust-lib/flowy-sdk/src/module.rs b/rust-lib/flowy-sdk/src/module.rs index ea427381ed..bdc712005f 100644 --- a/rust-lib/flowy-sdk/src/module.rs +++ b/rust-lib/flowy-sdk/src/module.rs @@ -1,21 +1,20 @@ +use crate::flowy_server::{ArcFlowyServer, FlowyServerMocker}; use flowy_dispatch::prelude::Module; use flowy_user::prelude::*; - -use crate::flowy_server::{ArcFlowyServer, MockFlowyServer}; -use flowy_database::DBConnection; -use flowy_user::errors::UserError; use flowy_workspace::prelude::*; + +use crate::deps_resolve::WorkspaceUserImpl; use std::sync::Arc; pub struct ModuleConfig { pub root: String, } -pub fn build_modules(config: ModuleConfig, server: ArcFlowyServer) -> Vec { +pub fn build_modules(config: ModuleConfig, _server: ArcFlowyServer) -> Vec { let user_session = Arc::new( UserSessionBuilder::new() .root_dir(&config.root) - .build(Arc::new(MockFlowyServer {})), + .build(Arc::new(FlowyServerMocker {})), ); let workspace_user_impl = Arc::new(WorkspaceUserImpl { @@ -27,27 +26,3 @@ pub fn build_modules(config: ModuleConfig, server: ArcFlowyServer) -> Vec, -} - -impl WorkspaceUser for WorkspaceUserImpl { - fn set_current_workspace(&self, id: &str) { unimplemented!() } - - fn get_current_workspace(&self) -> Result { - self.user_session.get_current_workspace().map_err(|e| { - ErrorBuilder::new(WorkspaceErrorCode::UserInternalError) - .error(e) - .build() - }) - } - - fn db_connection(&self) -> Result { - self.user_session.get_db_connection().map_err(|e| { - ErrorBuilder::new(WorkspaceErrorCode::DatabaseConnectionFail) - .error(e) - .build() - }) - } -} diff --git a/rust-lib/flowy-sqlite/src/conn_ext.rs b/rust-lib/flowy-sqlite/src/conn_ext.rs new file mode 100644 index 0000000000..2a39839178 --- /dev/null +++ b/rust-lib/flowy-sqlite/src/conn_ext.rs @@ -0,0 +1,30 @@ +use crate::errors::*; +use diesel::{ + dsl::sql, + expression::SqlLiteral, + query_dsl::LoadQuery, + Connection, + RunQueryDsl, + SqliteConnection, +}; + +pub trait ConnectionExtension: Connection { + fn query(&self, query: &str) -> Result + where + SqlLiteral: LoadQuery; + + fn exec(&self, query: impl AsRef) -> Result; +} + +impl ConnectionExtension for SqliteConnection { + fn query(&self, query: &str) -> Result + where + SqlLiteral: LoadQuery, + { + Ok(sql::(query).get_result(self)?) + } + + fn exec(&self, query: impl AsRef) -> Result { + Ok(SqliteConnection::execute(self, query.as_ref())?) + } +} diff --git a/rust-lib/flowy-sqlite/src/lib.rs b/rust-lib/flowy-sqlite/src/lib.rs index b631cf95b6..f6d5cbfd8d 100644 --- a/rust-lib/flowy-sqlite/src/lib.rs +++ b/rust-lib/flowy-sqlite/src/lib.rs @@ -1,7 +1,10 @@ +mod conn_ext; mod database; #[allow(deprecated, clippy::large_enum_variant)] mod errors; mod pool; +mod pragma; + pub use database::*; pub use pool::*; diff --git a/rust-lib/flowy-sqlite/src/pool.rs b/rust-lib/flowy-sqlite/src/pool.rs index ebc010eab1..62820a9362 100644 --- a/rust-lib/flowy-sqlite/src/pool.rs +++ b/rust-lib/flowy-sqlite/src/pool.rs @@ -1,6 +1,6 @@ -use crate::errors::*; +use crate::{errors::*, pragma::*}; use diesel::{connection::Connection, SqliteConnection}; -use r2d2::{ManageConnection, Pool}; +use r2d2::{CustomizeConnection, ManageConnection, Pool}; use scheduled_thread_pool::ScheduledThreadPool; use std::{ sync::{ @@ -34,10 +34,12 @@ impl ConnectionPool { let manager = ConnectionManager::new(uri); let thread_pool = DB_POOL.clone(); let config = Arc::new(config); + let customizer_config = DatabaseCustomizerConfig::default(); let pool = r2d2::Pool::builder() .thread_pool(thread_pool) .min_idle(Some(config.min_idle)) + .connection_customizer(Box::new(DatabaseCustomizer::new(customizer_config))) .max_size(config.max_size) .max_lifetime(None) .connection_timeout(config.connection_timeout) @@ -127,3 +129,48 @@ impl ManageConnection for ConnectionManager { impl ConnectionManager { pub fn new>(uri: S) -> Self { ConnectionManager { db_uri: uri.into() } } } + +#[derive(Debug)] +pub struct DatabaseCustomizerConfig { + pub(crate) journal_mode: SQLiteJournalMode, + pub(crate) synchronous: SQLiteSynchronous, + pub(crate) busy_timeout: i32, + pub(crate) secure_delete: bool, +} + +impl Default for DatabaseCustomizerConfig { + fn default() -> Self { + Self { + journal_mode: SQLiteJournalMode::WAL, + synchronous: SQLiteSynchronous::NORMAL, + busy_timeout: 5000, + secure_delete: true, + } + } +} + +#[derive(Debug)] +struct DatabaseCustomizer { + config: DatabaseCustomizerConfig, +} + +impl DatabaseCustomizer { + fn new(config: DatabaseCustomizerConfig) -> Self + where + Self: Sized, + { + Self { config } + } +} + +impl CustomizeConnection for DatabaseCustomizer { + fn on_acquire(&self, conn: &mut SqliteConnection) -> Result<()> { + conn.pragma_set_busy_timeout(self.config.busy_timeout)?; + if self.config.journal_mode != SQLiteJournalMode::WAL { + conn.pragma_set_journal_mode(self.config.journal_mode, None)?; + } + conn.pragma_set_synchronous(self.config.synchronous, None)?; + + Ok(()) + } +} diff --git a/rust-lib/flowy-sqlite/src/pragma.rs b/rust-lib/flowy-sqlite/src/pragma.rs new file mode 100644 index 0000000000..48c3df487c --- /dev/null +++ b/rust-lib/flowy-sqlite/src/pragma.rs @@ -0,0 +1,186 @@ +use crate::errors::{Error, Result}; +use diesel::{ + expression::SqlLiteral, + query_dsl::load_dsl::LoadQuery, + sql_types::{Integer, Text}, + SqliteConnection, +}; + +use crate::conn_ext::ConnectionExtension; +use std::{ + convert::{TryFrom, TryInto}, + fmt, + str::FromStr, +}; + +pub trait PragmaExtension: ConnectionExtension { + fn pragma(&self, key: &str, val: D, schema: Option<&str>) -> Result<()> { + let query = match schema { + Some(schema) => format!("PRAGMA {}.{} = '{}'", schema, key, val), + None => format!("PRAGMA {} = '{}'", key, val), + }; + log::trace!("SQLITE {}", query); + self.exec(&query)?; + Ok(()) + } + + fn pragma_ret( + &self, + key: &str, + val: D, + schema: Option<&str>, + ) -> Result + where + SqlLiteral: LoadQuery, + { + let query = match schema { + Some(schema) => format!("PRAGMA {}.{} = '{}'", schema, key, val), + None => format!("PRAGMA {} = '{}'", key, val), + }; + log::trace!("SQLITE {}", query); + Ok(self.query::(&query)?) + } + + fn pragma_get(&self, key: &str, schema: Option<&str>) -> Result + where + SqlLiteral: LoadQuery, + { + let query = match schema { + Some(schema) => format!("PRAGMA {}.{}", schema, key), + None => format!("PRAGMA {}", key), + }; + log::trace!("SQLITE {}", query); + Ok(self.query::(&query)?) + } + + fn pragma_set_busy_timeout(&self, timeout_ms: i32) -> Result { + self.pragma_ret::("busy_timeout", timeout_ms, None) + } + + fn pragma_get_busy_timeout(&self) -> Result { + self.pragma_get::("busy_timeout", None) + } + + fn pragma_set_journal_mode( + &self, + mode: SQLiteJournalMode, + schema: Option<&str>, + ) -> Result { + self.pragma_ret::("journal_mode", mode, schema) + } + + fn pragma_get_journal_mode(&self, schema: Option<&str>) -> Result { + Ok(self + .pragma_get::("journal_mode", schema)? + .parse()?) + } + + fn pragma_set_synchronous( + &self, + synchronous: SQLiteSynchronous, + schema: Option<&str>, + ) -> Result<()> { + self.pragma("synchronous", synchronous as u8, schema) + } + + fn pragma_get_synchronous(&self, schema: Option<&str>) -> Result { + Ok(self + .pragma_get::("synchronous", schema)? + .try_into()?) + } +} +impl PragmaExtension for SqliteConnection {} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum SQLiteJournalMode { + DELETE, + TRUNCATE, + PERSIST, + MEMORY, + WAL, + OFF, +} + +impl fmt::Display for SQLiteJournalMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + Self::DELETE => "DELETE", + Self::TRUNCATE => "TRUNCATE", + Self::PERSIST => "PERSIST", + Self::MEMORY => "MEMORY", + Self::WAL => "WAL", + Self::OFF => "OFF", + } + ) + } +} + +impl FromStr for SQLiteJournalMode { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s.to_uppercase().as_ref() { + "DELETE" => Ok(Self::DELETE), + "TRUNCATE" => Ok(Self::TRUNCATE), + "PERSIST" => Ok(Self::PERSIST), + "MEMORY" => Ok(Self::MEMORY), + "WAL" => Ok(Self::WAL), + "OFF" => Ok(Self::OFF), + _ => Err(format!("Unknown value {} for JournalMode", s).into()), + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum SQLiteSynchronous { + EXTRA = 3, + FULL = 2, + NORMAL = 1, + OFF = 0, +} + +impl fmt::Display for SQLiteSynchronous { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + Self::OFF => "OFF", + Self::NORMAL => "NORMAL", + Self::FULL => "FULL", + Self::EXTRA => "EXTRA", + } + ) + } +} + +impl TryFrom for SQLiteSynchronous { + type Error = Error; + + fn try_from(v: i32) -> Result { + match v { + 0 => Ok(Self::OFF), + 1 => Ok(Self::NORMAL), + 2 => Ok(Self::FULL), + 3 => Ok(Self::EXTRA), + _ => Err(format!("Unknown value {} for Synchronous", v).into()), + } + } +} + +impl FromStr for SQLiteSynchronous { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s.to_uppercase().as_ref() { + "0" | "OFF" => Ok(Self::OFF), + "1" | "NORMAL" => Ok(Self::NORMAL), + "2" | "FULL" => Ok(Self::FULL), + "3" | "EXTRA" => Ok(Self::EXTRA), + _ => Err(format!("Unknown value {} for Synchronous", s).into()), + } + } +} diff --git a/rust-lib/flowy-test/Cargo.toml b/rust-lib/flowy-test/Cargo.toml index fc28e6525f..c86b3ea2ea 100644 --- a/rust-lib/flowy-test/Cargo.toml +++ b/rust-lib/flowy-test/Cargo.toml @@ -9,6 +9,8 @@ edition = "2018" flowy-sdk = { path = "../flowy-sdk"} flowy-dispatch = { path = "../flowy-dispatch"} flowy-user = { path = "../flowy-user"} +flowy-workspace = { path = "../flowy-workspace"} +flowy-infra = { path = "../flowy-infra"} serde = { version = "1.0", features = ["derive"] } bincode = { version = "1.3"} diff --git a/rust-lib/flowy-test/src/builder.rs b/rust-lib/flowy-test/src/builder.rs new file mode 100644 index 0000000000..e7a9c3b1b0 --- /dev/null +++ b/rust-lib/flowy-test/src/builder.rs @@ -0,0 +1,164 @@ +use flowy_dispatch::prelude::{FromBytes, ToBytes}; +use flowy_user::entities::UserDetail; +use std::{ + fmt::{Debug, Display}, + hash::Hash, +}; + +use crate::{ + helper::valid_email, + tester::{TesterContext, TesterTrait}, +}; +use flowy_user::errors::UserError; +use flowy_workspace::errors::WorkspaceError; +use std::{marker::PhantomData, sync::Once}; +static INIT: Once = Once::new(); + +pub type WorkspaceTestBuilder = TestBuilder>; +impl WorkspaceTestBuilder { + pub fn new() -> Self { + let mut builder = Self { + tester: Box::new(FixedUserTester::::new()), + user_detail: None, + }; + + INIT.call_once(|| builder.login_if_need()); + builder + } +} + +pub type UserTestBuilder = TestBuilder>; +impl UserTestBuilder { + pub fn new() -> Self { + let builder = Self { + tester: Box::new(RandomUserTester::::new()), + user_detail: None, + }; + + builder + } + + pub fn reset(mut self) -> Self { self.login() } +} + +pub struct TestBuilder { + pub tester: Box, + pub user_detail: Option, +} + +impl TestBuilder +where + T: TesterTrait, +{ + pub fn login(mut self) -> Self { + let user_detail = self.tester.login(); + self.user_detail = Some(user_detail); + self + } + + pub fn login_if_need(&mut self) { + let user_detail = self.tester.login_if_need(); + self.user_detail = Some(user_detail); + } + + pub fn logout(self) -> Self { + // self.tester.logout(); + self + } + + pub fn request

(mut self, request: P) -> Self + where + P: ToBytes, + { + self.tester.set_payload(request); + self + } + + pub fn event(mut self, event: E) -> Self + where + E: Eq + Hash + Debug + Clone + Display, + { + self.tester.set_event(event); + self + } + + pub fn sync_send(mut self) -> Self { + self.tester.sync_send(); + self + } + + pub fn parse(mut self) -> R + where + R: FromBytes, + { + self.tester.parse::() + } + + pub fn error(mut self) -> ::Error { self.tester.error() } + + pub fn assert_error(mut self) -> Self { + self.tester.assert_error(); + self + } + + pub fn assert_success(mut self) -> Self { + self.tester.assert_success(); + self + } +} + +pub struct RandomUserTester { + context: TesterContext, + err_phantom: PhantomData, +} + +impl RandomUserTester +where + Error: FromBytes + Debug, +{ + pub fn new() -> Self { + Self { + context: TesterContext::default(), + err_phantom: PhantomData, + } + } +} + +impl TesterTrait for RandomUserTester +where + Error: FromBytes + Debug, +{ + type Error = Error; + + fn mut_context(&mut self) -> &mut TesterContext { &mut self.context } + + fn context(&self) -> &TesterContext { &self.context } +} + +pub struct FixedUserTester { + context: TesterContext, + err_phantom: PhantomData, +} + +impl FixedUserTester +where + Error: FromBytes + Debug, +{ + pub fn new() -> Self { + Self { + context: TesterContext::new(valid_email()), + err_phantom: PhantomData, + } + } +} + +impl TesterTrait for FixedUserTester +where + Error: FromBytes + Debug, +{ + type Error = Error; + + fn mut_context(&mut self) -> &mut TesterContext { &mut self.context } + + fn context(&self) -> &TesterContext { &self.context } +} diff --git a/rust-lib/flowy-test/src/helper.rs b/rust-lib/flowy-test/src/helper.rs new file mode 100644 index 0000000000..f13adeba12 --- /dev/null +++ b/rust-lib/flowy-test/src/helper.rs @@ -0,0 +1,24 @@ +use flowy_infra::uuid; +use std::{fs, path::PathBuf}; + +pub fn root_dir() -> String { + // https://doc.rust-lang.org/cargo/reference/environment-variables.html + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or("./".to_owned()); + let mut path_buf = fs::canonicalize(&PathBuf::from(&manifest_dir)).unwrap(); + path_buf.pop(); // rust-lib + path_buf.push("flowy-test"); + path_buf.push("temp"); + path_buf.push("flowy"); + + let root_dir = path_buf.to_str().unwrap().to_string(); + if !std::path::Path::new(&root_dir).exists() { + std::fs::create_dir_all(&root_dir).unwrap(); + } + root_dir +} + +pub fn random_valid_email() -> String { format!("{}@appflowy.io", uuid()) } + +pub fn valid_email() -> String { "annie@appflowy.io".to_string() } + +pub fn valid_password() -> String { "HelloWorld!123".to_string() } diff --git a/rust-lib/flowy-test/src/lib.rs b/rust-lib/flowy-test/src/lib.rs index 9c89eafc34..15187a56c5 100644 --- a/rust-lib/flowy-test/src/lib.rs +++ b/rust-lib/flowy-test/src/lib.rs @@ -1,253 +1,24 @@ -use flowy_dispatch::prelude::*; -pub use flowy_sdk::*; -use flowy_user::{ - errors::UserError, - event::UserEvent::{SignIn, SignOut}, - prelude::*, -}; -use std::{ - convert::TryFrom, - fmt::{Debug, Display}, - fs, - hash::Hash, - marker::PhantomData, - path::PathBuf, - sync::Once, - thread, -}; +pub mod builder; +mod helper; +mod tester; + +use crate::helper::root_dir; +use flowy_sdk::{ArcFlowyServer, FlowySDK}; +use std::sync::Once; pub mod prelude { - pub use crate::Tester; + pub use crate::{ + builder::{TestBuilder, *}, + helper::*, + }; pub use flowy_dispatch::prelude::*; - pub use std::convert::TryFrom; } static INIT: Once = Once::new(); -pub fn init_sdk() { +pub fn init_test_sdk(server: ArcFlowyServer) { let root_dir = root_dir(); INIT.call_once(|| { - FlowySDK::new(&root_dir).construct(); + FlowySDK::construct_with(&root_dir, server); }); } - -fn root_dir() -> String { - // https://doc.rust-lang.org/cargo/reference/environment-variables.html - let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or("./".to_owned()); - let mut path_buf = fs::canonicalize(&PathBuf::from(&manifest_dir)).unwrap(); - path_buf.pop(); // rust-lib - path_buf.push("flowy-test"); - path_buf.push("temp"); - path_buf.push("flowy"); - - let root_dir = path_buf.to_str().unwrap().to_string(); - if !std::path::Path::new(&root_dir).exists() { - std::fs::create_dir_all(&root_dir).unwrap(); - } - root_dir -} - -pub struct TestBuilder { - login: Option, - inner: Option>, - pub user_detail: Option, -} - -impl TestBuilder -where - Error: FromBytes + Debug, -{ - pub fn new() -> Self { - TestBuilder:: { - login: None, - inner: None, - user_detail: None, - } - } - - pub fn login(mut self) -> Self { - let user_detail = new_user_after_login(); - self.user_detail = Some(user_detail); - self - } - - pub fn logout(self) -> Self { - init_sdk(); - let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut)); - self - } - - pub fn event(mut self, event: E) -> Self - where - E: Eq + Hash + Debug + Clone + Display, - { - self.inner = Some(Tester::::new(event)); - self - } - - pub fn request

(mut self, request: P) -> Self - where - P: ToBytes, - { - let mut inner = self.inner.unwrap(); - self.inner = Some(inner.request(request)); - self - } - - pub fn sync_send(mut self) -> Self { - let inner = self.inner.take().unwrap(); - self.inner = Some(inner.sync_send()); - self - } - - pub fn parse(mut self) -> R - where - R: FromBytes, - { - let inner = self.inner.take().unwrap(); - inner.parse::() - } - - pub fn error(mut self) -> Error { - let inner = self.inner.take().unwrap(); - inner.error() - } - - pub fn assert_error(mut self) -> Self { - let inner = self.inner.take().unwrap(); - self.inner = Some(inner.assert_error()); - self - } - - pub fn assert_success(mut self) -> Self { - let inner = self.inner.take().unwrap(); - self.inner = Some(inner.assert_success()); - self - } -} - -pub struct Tester { - inner_request: Option, - assert_status_code: Option, - response: Option, - err_phantom: PhantomData, - user_detail: Option, -} - -impl Tester -where - Error: FromBytes + Debug, -{ - pub fn new(event: E) -> Self - where - E: Eq + Hash + Debug + Clone + Display, - { - init_sdk(); - log::trace!( - "{:?} thread started: thread_id= {}", - thread::current(), - thread_id::get() - ); - - Self { - inner_request: Some(ModuleRequest::new(event)), - assert_status_code: None, - response: None, - err_phantom: PhantomData, - user_detail: None, - } - } - - pub fn request

(mut self, request: P) -> Self - where - P: ToBytes, - { - let mut inner_request = self.inner_request.take().unwrap(); - let bytes = request.into_bytes().unwrap(); - inner_request = inner_request.payload(bytes); - self.inner_request = Some(inner_request); - self - } - - pub fn assert_status_code(mut self, status_code: StatusCode) -> Self { - self.assert_status_code = Some(status_code); - self - } - - pub fn assert_error(mut self) -> Self { - self.assert_status_code = Some(StatusCode::Err); - self - } - - pub fn assert_success(mut self) -> Self { - self.assert_status_code = Some(StatusCode::Ok); - self - } - - pub async fn async_send(mut self) -> Self { - assert_eq!(self.inner_request.is_some(), true, "must set event"); - - let resp = - EventDispatch::async_send(self.inner_request.take().unwrap(), |_| Box::pin(async {})) - .await; - check(&resp, &self.assert_status_code); - self.response = Some(resp); - self - } - - pub fn sync_send(mut self) -> Self { - let resp = EventDispatch::sync_send(self.inner_request.take().unwrap()); - check(&resp, &self.assert_status_code); - self.response = Some(resp); - self - } - - pub fn parse(self) -> R - where - R: FromBytes, - { - let response = self.response.unwrap(); - match response.parse::() { - Ok(Ok(data)) => data, - Ok(Err(e)) => panic!("parse failed: {:?}", e), - Err(e) => panic!("Internal error: {:?}", e), - } - } - - pub fn error(self) -> Error { - let response = self.response.unwrap(); - assert_eq!(response.status_code, StatusCode::Err); - >::try_from(response.payload) - .unwrap() - .into_inner() - } -} - -fn check(response: &EventResponse, status_code: &Option) { - if let Some(ref status_code) = status_code { - if &response.status_code != status_code { - eprintln!("{:#?}", response); - } - assert_eq!(&response.status_code, status_code) - } -} - -fn new_user_after_login() -> UserDetail { - init_sdk(); - let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut)); - let request = SignInRequest { - email: valid_email(), - password: valid_password(), - }; - - let user_detail = Tester::::new(SignIn) - .request(request) - .sync_send() - .parse::(); - - user_detail -} - -pub(crate) fn valid_email() -> String { "annie@appflowy.io".to_string() } - -pub(crate) fn valid_password() -> String { "HelloWorld!123".to_string() } diff --git a/rust-lib/flowy-test/src/tester.rs b/rust-lib/flowy-test/src/tester.rs new file mode 100644 index 0000000000..5330ffc92e --- /dev/null +++ b/rust-lib/flowy-test/src/tester.rs @@ -0,0 +1,133 @@ +use crate::{ + helper::{random_valid_email, valid_password}, + init_test_sdk, +}; +use flowy_dispatch::prelude::*; +pub use flowy_sdk::*; +use flowy_user::{ + errors::UserError, + event::UserEvent::{GetStatus, SignIn, SignOut}, + prelude::*, +}; +use std::{ + convert::TryFrom, + fmt::{Debug, Display}, + hash::Hash, + sync::Arc, +}; + +pub struct TesterContext { + request: Option, + response: Option, + status_code: StatusCode, + server: ArcFlowyServer, + user_email: String, +} + +impl TesterContext { + pub fn new(email: String) -> Self { + let mut ctx = TesterContext::default(); + ctx.user_email = email; + ctx + } +} + +impl std::default::Default for TesterContext { + fn default() -> Self { + Self { + request: None, + status_code: StatusCode::Ok, + response: None, + server: Arc::new(FlowyServerMocker {}), + user_email: random_valid_email(), + } + } +} + +pub trait TesterTrait { + type Error: FromBytes + Debug; + + fn mut_context(&mut self) -> &mut TesterContext; + + fn context(&self) -> &TesterContext; + + fn assert_error(&mut self) { self.mut_context().status_code = StatusCode::Err; } + + fn assert_success(&mut self) { self.mut_context().status_code = StatusCode::Ok; } + + fn set_event(&mut self, event: E) + where + E: Eq + Hash + Debug + Clone + Display, + { + init_test_sdk(self.context().server.clone()); + self.mut_context().request = Some(ModuleRequest::new(event)); + } + + fn set_payload

(&mut self, payload: P) + where + P: ToBytes, + { + let bytes = payload.into_bytes().unwrap(); + let module_request = self.mut_context().request.take().unwrap(); + self.mut_context().request = Some(module_request.payload(bytes)); + } + + fn sync_send(&mut self) { + let resp = EventDispatch::sync_send(self.mut_context().request.take().unwrap()); + self.mut_context().response = Some(resp); + } + + fn parse(&mut self) -> R + where + R: FromBytes, + { + let response = self.mut_context().response.clone().unwrap(); + match response.parse::() { + Ok(Ok(data)) => data, + Ok(Err(e)) => panic!("parse failed: {:?}", e), + Err(e) => panic!("Internal error: {:?}", e), + } + } + + fn error(&mut self) -> Self::Error { + let response = self.mut_context().response.clone().unwrap(); + assert_eq!(response.status_code, StatusCode::Err); + >::try_from(response.payload) + .unwrap() + .into_inner() + } + + fn login(&self) -> UserDetail { + init_test_sdk(self.context().server.clone()); + let payload = SignInRequest { + email: self.context().user_email.clone(), + password: valid_password(), + } + .into_bytes() + .unwrap(); + + let request = ModuleRequest::new(SignIn).payload(payload); + let user_detail = EventDispatch::sync_send(request) + .parse::() + .unwrap() + .unwrap(); + + user_detail + } + + fn login_if_need(&self) -> UserDetail { + init_test_sdk(self.context().server.clone()); + match EventDispatch::sync_send(ModuleRequest::new(GetStatus)) + .parse::() + .unwrap() + { + Ok(user_detail) => user_detail, + Err(e) => self.login(), + } + } + + fn logout(&self) { + init_test_sdk(self.context().server.clone()); + let _ = EventDispatch::sync_send(ModuleRequest::new(SignOut)); + } +} diff --git a/rust-lib/flowy-user/Cargo.toml b/rust-lib/flowy-user/Cargo.toml index 44dffac38f..db0be3480b 100644 --- a/rust-lib/flowy-user/Cargo.toml +++ b/rust-lib/flowy-user/Cargo.toml @@ -26,6 +26,10 @@ lazy_static = "1.4.0" fancy-regex = "0.5.0" diesel = {version = "1.4.7", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} +thread_local = "1.1.3" +thread-id = "3.3.0" +once_cell = "1.7.2" +parking_lot = "0.11" [dev-dependencies] quickcheck = "0.9.2" diff --git a/rust-lib/flowy-user/src/entities/user_detail.rs b/rust-lib/flowy-user/src/entities/user_detail.rs index e59a421a7a..eaf1e4e99a 100644 --- a/rust-lib/flowy-user/src/entities/user_detail.rs +++ b/rust-lib/flowy-user/src/entities/user_detail.rs @@ -29,9 +29,9 @@ pub struct UserDetail { pub workspace: String, } -use crate::sql_tables::User; -impl std::convert::From for UserDetail { - fn from(user: User) -> Self { +use crate::sql_tables::UserTable; +impl std::convert::From for UserDetail { + fn from(user: UserTable) -> Self { UserDetail { id: user.id, email: user.email, diff --git a/rust-lib/flowy-user/src/entities/user_update.rs b/rust-lib/flowy-user/src/entities/user_update.rs index 5d8a2da342..ab072bd22f 100644 --- a/rust-lib/flowy-user/src/entities/user_update.rs +++ b/rust-lib/flowy-user/src/entities/user_update.rs @@ -23,6 +23,35 @@ pub struct UpdateUserRequest { pub password: Option, } +impl UpdateUserRequest { + pub fn new(id: &str) -> Self { + Self { + id: id.to_owned(), + ..Default::default() + } + } + + pub fn name(mut self, name: &str) -> Self { + self.name = Some(name.to_owned()); + self + } + + pub fn email(mut self, email: &str) -> Self { + self.email = Some(email.to_owned()); + self + } + + pub fn workspace(mut self, workspace: &str) -> Self { + self.workspace = Some(workspace.to_owned()); + self + } + + pub fn password(mut self, password: &str) -> Self { + self.password = Some(password.to_owned()); + self + } +} + pub struct UpdateUserParams { pub id: String, pub name: Option, diff --git a/rust-lib/flowy-user/src/errors.rs b/rust-lib/flowy-user/src/errors.rs index b2ff67213b..384793468f 100644 --- a/rust-lib/flowy-user/src/errors.rs +++ b/rust-lib/flowy-user/src/errors.rs @@ -26,15 +26,15 @@ pub enum UserErrorCode { #[display(fmt = "Unknown")] Unknown = 0, #[display(fmt = "Database init failed")] - DatabaseInitFailed = 1, + UserDatabaseInitFailed = 1, #[display(fmt = "Get database write lock failed")] - DatabaseWriteLocked = 2, + UserDatabaseWriteLocked = 2, #[display(fmt = "Get database read lock failed")] - DatabaseReadLocked = 3, + UserDatabaseReadLocked = 3, #[display(fmt = "Opening database is not belonging to the current user")] - DatabaseUserDidNotMatch = 4, + UserDatabaseDidNotMatch = 4, #[display(fmt = "Database internal error")] - DatabaseInternalError = 5, + UserDatabaseInternalError = 5, #[display(fmt = "User not login yet")] UserNotLoginYet = 10, @@ -53,6 +53,8 @@ pub enum UserErrorCode { UserWorkspaceInvalid = 23, #[display(fmt = "User id is invalid")] UserIdInvalid = 24, + #[display(fmt = "Create user default workspace failed")] + CreateDefaultWorkspaceFailed = 25, } impl std::default::Default for UserErrorCode { @@ -61,15 +63,44 @@ impl std::default::Default for UserErrorCode { impl std::convert::From for UserError { fn from(error: flowy_database::result::Error) -> Self { - ErrorBuilder::new(UserErrorCode::DatabaseInternalError) + ErrorBuilder::new(UserErrorCode::UserDatabaseInternalError) .error(error) .build() } } - +use diesel::result::DatabaseErrorKind; impl std::convert::From for UserError { fn from(error: flowy_sqlite::Error) -> Self { - ErrorBuilder::new(UserErrorCode::DatabaseInternalError) + // match error.kind() { + // ErrorKind::Msg(_) => {}, + // ErrorKind::R2D2(_) => {}, + // ErrorKind::Migrations(_) => {}, + // ErrorKind::Diesel(diesel_err) => match diesel_err { + // Error::InvalidCString(_) => {}, + // Error::DatabaseError(kind, _) => { + // match kind { + // DatabaseErrorKind::UniqueViolation => { + // + // } + // _ => {} + // } + // + // }, + // Error::NotFound => {}, + // Error::QueryBuilderError(_) => {}, + // Error::DeserializationError(_) => {}, + // Error::SerializationError(_) => {}, + // Error::RollbackTransaction => {}, + // Error::AlreadyInTransaction => {}, + // Error::__Nonexhaustive => {}, + // }, + // ErrorKind::Connection(_) => {}, + // ErrorKind::Io(_) => {}, + // ErrorKind::UnknownMigrationExists(_) => {}, + // ErrorKind::__Nonexhaustive { .. } => {}, + // } + + ErrorBuilder::new(UserErrorCode::UserDatabaseInternalError) .error(error) .build() } diff --git a/rust-lib/flowy-user/src/handlers/user_handler.rs b/rust-lib/flowy-user/src/handlers/user_handler.rs index 34b627e2a0..7cb31b3d88 100644 --- a/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/rust-lib/flowy-user/src/handlers/user_handler.rs @@ -5,12 +5,12 @@ use std::{convert::TryInto, sync::Arc}; pub async fn user_get_status_handler( session: ModuleData>, ) -> ResponseResult { - let user_detail = session.current_user_detail()?; + let user_detail = session.user_detail()?; response_ok(user_detail) } pub async fn sign_out_handler(session: ModuleData>) -> Result<(), UserError> { - let _ = session.sign_out().await?; + let _ = session.sign_out()?; Ok(()) } @@ -19,6 +19,6 @@ pub async fn update_user_handler( session: ModuleData>, ) -> ResponseResult { let params: UpdateUserParams = data.into_inner().try_into()?; - let user_detail = session.update_user(params).await?; + let user_detail = session.update_user(params)?; response_ok(user_detail) } diff --git a/rust-lib/flowy-user/src/protobuf/model/errors.rs b/rust-lib/flowy-user/src/protobuf/model/errors.rs index 56637c911d..5c5e9468e0 100644 --- a/rust-lib/flowy-user/src/protobuf/model/errors.rs +++ b/rust-lib/flowy-user/src/protobuf/model/errors.rs @@ -216,11 +216,11 @@ impl ::protobuf::reflect::ProtobufValue for UserError { #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum UserErrorCode { Unknown = 0, - DatabaseInitFailed = 1, - DatabaseWriteLocked = 2, - DatabaseReadLocked = 3, - DatabaseUserDidNotMatch = 4, - DatabaseInternalError = 5, + UserDatabaseInitFailed = 1, + UserDatabaseWriteLocked = 2, + UserDatabaseReadLocked = 3, + UserDatabaseDidNotMatch = 4, + UserDatabaseInternalError = 5, UserNotLoginYet = 10, ReadCurrentIdFailed = 11, WriteCurrentIdFailed = 12, @@ -229,6 +229,7 @@ pub enum UserErrorCode { UserNameInvalid = 22, UserWorkspaceInvalid = 23, UserIdInvalid = 24, + CreateDefaultWorkspaceFailed = 25, } impl ::protobuf::ProtobufEnum for UserErrorCode { @@ -239,11 +240,11 @@ impl ::protobuf::ProtobufEnum for UserErrorCode { fn from_i32(value: i32) -> ::std::option::Option { match value { 0 => ::std::option::Option::Some(UserErrorCode::Unknown), - 1 => ::std::option::Option::Some(UserErrorCode::DatabaseInitFailed), - 2 => ::std::option::Option::Some(UserErrorCode::DatabaseWriteLocked), - 3 => ::std::option::Option::Some(UserErrorCode::DatabaseReadLocked), - 4 => ::std::option::Option::Some(UserErrorCode::DatabaseUserDidNotMatch), - 5 => ::std::option::Option::Some(UserErrorCode::DatabaseInternalError), + 1 => ::std::option::Option::Some(UserErrorCode::UserDatabaseInitFailed), + 2 => ::std::option::Option::Some(UserErrorCode::UserDatabaseWriteLocked), + 3 => ::std::option::Option::Some(UserErrorCode::UserDatabaseReadLocked), + 4 => ::std::option::Option::Some(UserErrorCode::UserDatabaseDidNotMatch), + 5 => ::std::option::Option::Some(UserErrorCode::UserDatabaseInternalError), 10 => ::std::option::Option::Some(UserErrorCode::UserNotLoginYet), 11 => ::std::option::Option::Some(UserErrorCode::ReadCurrentIdFailed), 12 => ::std::option::Option::Some(UserErrorCode::WriteCurrentIdFailed), @@ -252,6 +253,7 @@ impl ::protobuf::ProtobufEnum for UserErrorCode { 22 => ::std::option::Option::Some(UserErrorCode::UserNameInvalid), 23 => ::std::option::Option::Some(UserErrorCode::UserWorkspaceInvalid), 24 => ::std::option::Option::Some(UserErrorCode::UserIdInvalid), + 25 => ::std::option::Option::Some(UserErrorCode::CreateDefaultWorkspaceFailed), _ => ::std::option::Option::None } } @@ -259,11 +261,11 @@ impl ::protobuf::ProtobufEnum for UserErrorCode { fn values() -> &'static [Self] { static values: &'static [UserErrorCode] = &[ UserErrorCode::Unknown, - UserErrorCode::DatabaseInitFailed, - UserErrorCode::DatabaseWriteLocked, - UserErrorCode::DatabaseReadLocked, - UserErrorCode::DatabaseUserDidNotMatch, - UserErrorCode::DatabaseInternalError, + UserErrorCode::UserDatabaseInitFailed, + UserErrorCode::UserDatabaseWriteLocked, + UserErrorCode::UserDatabaseReadLocked, + UserErrorCode::UserDatabaseDidNotMatch, + UserErrorCode::UserDatabaseInternalError, UserErrorCode::UserNotLoginYet, UserErrorCode::ReadCurrentIdFailed, UserErrorCode::WriteCurrentIdFailed, @@ -272,6 +274,7 @@ impl ::protobuf::ProtobufEnum for UserErrorCode { UserErrorCode::UserNameInvalid, UserErrorCode::UserWorkspaceInvalid, UserErrorCode::UserIdInvalid, + UserErrorCode::CreateDefaultWorkspaceFailed, ]; values } @@ -302,51 +305,54 @@ impl ::protobuf::reflect::ProtobufValue for UserErrorCode { static file_descriptor_proto_data: &'static [u8] = b"\ \n\x0cerrors.proto\"A\n\tUserError\x12\"\n\x04code\x18\x01\x20\x01(\x0e2\ \x0e.UserErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*\ - \xce\x02\n\rUserErrorCode\x12\x0b\n\x07Unknown\x10\0\x12\x16\n\x12Databa\ - seInitFailed\x10\x01\x12\x17\n\x13DatabaseWriteLocked\x10\x02\x12\x16\n\ - \x12DatabaseReadLocked\x10\x03\x12\x1b\n\x17DatabaseUserDidNotMatch\x10\ - \x04\x12\x19\n\x15DatabaseInternalError\x10\x05\x12\x13\n\x0fUserNotLogi\ - nYet\x10\n\x12\x17\n\x13ReadCurrentIdFailed\x10\x0b\x12\x18\n\x14WriteCu\ - rrentIdFailed\x10\x0c\x12\x10\n\x0cEmailInvalid\x10\x14\x12\x13\n\x0fPas\ - swordInvalid\x10\x15\x12\x13\n\x0fUserNameInvalid\x10\x16\x12\x18\n\x14U\ - serWorkspaceInvalid\x10\x17\x12\x11\n\rUserIdInvalid\x10\x18J\xee\x05\n\ - \x06\x12\x04\0\0\x15\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\ + \x80\x03\n\rUserErrorCode\x12\x0b\n\x07Unknown\x10\0\x12\x1a\n\x16UserDa\ + tabaseInitFailed\x10\x01\x12\x1b\n\x17UserDatabaseWriteLocked\x10\x02\ + \x12\x1a\n\x16UserDatabaseReadLocked\x10\x03\x12\x1b\n\x17UserDatabaseDi\ + dNotMatch\x10\x04\x12\x1d\n\x19UserDatabaseInternalError\x10\x05\x12\x13\ + \n\x0fUserNotLoginYet\x10\n\x12\x17\n\x13ReadCurrentIdFailed\x10\x0b\x12\ + \x18\n\x14WriteCurrentIdFailed\x10\x0c\x12\x10\n\x0cEmailInvalid\x10\x14\ + \x12\x13\n\x0fPasswordInvalid\x10\x15\x12\x13\n\x0fUserNameInvalid\x10\ + \x16\x12\x18\n\x14UserWorkspaceInvalid\x10\x17\x12\x11\n\rUserIdInvalid\ + \x10\x18\x12\x20\n\x1cCreateDefaultWorkspaceFailed\x10\x19J\x97\x06\n\ + \x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\ \x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x11\n\x0b\n\ \x04\x04\0\x02\0\x12\x03\x03\x04\x1b\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\ \x03\x04\x11\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x12\x16\n\x0c\n\x05\ \x04\0\x02\0\x03\x12\x03\x03\x19\x1a\n\x0b\n\x04\x04\0\x02\x01\x12\x03\ \x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\ \x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\ - \x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x15\x01\n\n\n\x03\x05\0\ + \x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x16\x01\n\n\n\x03\x05\0\ \x01\x12\x03\x06\x05\x12\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\x04\x10\n\ \x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\x05\0\x02\0\ - \x02\x12\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x1b\n\ - \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x16\n\x0c\n\x05\x05\0\x02\ - \x01\x02\x12\x03\x08\x19\x1a\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x1c\ - \n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x17\n\x0c\n\x05\x05\0\x02\ - \x02\x02\x12\x03\t\x1a\x1b\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\x04\x1b\n\ - \x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x16\n\x0c\n\x05\x05\0\x02\x03\ - \x02\x12\x03\n\x19\x1a\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\x04\x20\n\ + \x02\x12\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x1f\n\ + \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x1a\n\x0c\n\x05\x05\0\x02\ + \x01\x02\x12\x03\x08\x1d\x1e\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x20\ + \n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x1b\n\x0c\n\x05\x05\0\x02\ + \x02\x02\x12\x03\t\x1e\x1f\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\x04\x1f\n\ + \x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x1a\n\x0c\n\x05\x05\0\x02\x03\ + \x02\x12\x03\n\x1d\x1e\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\x04\x20\n\ \x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x1b\n\x0c\n\x05\x05\0\x02\ - \x04\x02\x12\x03\x0b\x1e\x1f\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x0c\x04\ - \x1e\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x19\n\x0c\n\x05\x05\0\ - \x02\x05\x02\x12\x03\x0c\x1c\x1d\n\x0b\n\x04\x05\0\x02\x06\x12\x03\r\x04\ - \x19\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x13\n\x0c\n\x05\x05\0\ - \x02\x06\x02\x12\x03\r\x16\x18\n\x0b\n\x04\x05\0\x02\x07\x12\x03\x0e\x04\ - \x1d\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x17\n\x0c\n\x05\x05\0\ - \x02\x07\x02\x12\x03\x0e\x1a\x1c\n\x0b\n\x04\x05\0\x02\x08\x12\x03\x0f\ - \x04\x1e\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x18\n\x0c\n\x05\ - \x05\0\x02\x08\x02\x12\x03\x0f\x1b\x1d\n\x0b\n\x04\x05\0\x02\t\x12\x03\ - \x10\x04\x16\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x04\x10\n\x0c\n\x05\ - \x05\0\x02\t\x02\x12\x03\x10\x13\x15\n\x0b\n\x04\x05\0\x02\n\x12\x03\x11\ - \x04\x19\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\x13\n\x0c\n\x05\x05\ - \0\x02\n\x02\x12\x03\x11\x16\x18\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x12\ - \x04\x19\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\ - \x05\0\x02\x0b\x02\x12\x03\x12\x16\x18\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\ - \x13\x04\x1e\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x13\x04\x18\n\x0c\n\ - \x05\x05\0\x02\x0c\x02\x12\x03\x13\x1b\x1d\n\x0b\n\x04\x05\0\x02\r\x12\ - \x03\x14\x04\x17\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\x14\x04\x11\n\x0c\n\ - \x05\x05\0\x02\r\x02\x12\x03\x14\x14\x16b\x06proto3\ + \x04\x02\x12\x03\x0b\x1e\x1f\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x0c\x04\"\ + \n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x1d\n\x0c\n\x05\x05\0\x02\ + \x05\x02\x12\x03\x0c\x20!\n\x0b\n\x04\x05\0\x02\x06\x12\x03\r\x04\x19\n\ + \x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x13\n\x0c\n\x05\x05\0\x02\x06\ + \x02\x12\x03\r\x16\x18\n\x0b\n\x04\x05\0\x02\x07\x12\x03\x0e\x04\x1d\n\ + \x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x17\n\x0c\n\x05\x05\0\x02\ + \x07\x02\x12\x03\x0e\x1a\x1c\n\x0b\n\x04\x05\0\x02\x08\x12\x03\x0f\x04\ + \x1e\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x18\n\x0c\n\x05\x05\0\ + \x02\x08\x02\x12\x03\x0f\x1b\x1d\n\x0b\n\x04\x05\0\x02\t\x12\x03\x10\x04\ + \x16\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x04\x10\n\x0c\n\x05\x05\0\ + \x02\t\x02\x12\x03\x10\x13\x15\n\x0b\n\x04\x05\0\x02\n\x12\x03\x11\x04\ + \x19\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\x13\n\x0c\n\x05\x05\0\ + \x02\n\x02\x12\x03\x11\x16\x18\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x12\x04\ + \x19\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\x05\0\ + \x02\x0b\x02\x12\x03\x12\x16\x18\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\x13\ + \x04\x1e\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x13\x04\x18\n\x0c\n\x05\ + \x05\0\x02\x0c\x02\x12\x03\x13\x1b\x1d\n\x0b\n\x04\x05\0\x02\r\x12\x03\ + \x14\x04\x17\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\x14\x04\x11\n\x0c\n\x05\ + \x05\0\x02\r\x02\x12\x03\x14\x14\x16\n\x0b\n\x04\x05\0\x02\x0e\x12\x03\ + \x15\x04&\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\x15\x04\x20\n\x0c\n\x05\ + \x05\0\x02\x0e\x02\x12\x03\x15#%b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/rust-lib/flowy-user/src/protobuf/proto/errors.proto b/rust-lib/flowy-user/src/protobuf/proto/errors.proto index 0d880f5fa1..1e644873fa 100644 --- a/rust-lib/flowy-user/src/protobuf/proto/errors.proto +++ b/rust-lib/flowy-user/src/protobuf/proto/errors.proto @@ -6,11 +6,11 @@ message UserError { } enum UserErrorCode { Unknown = 0; - DatabaseInitFailed = 1; - DatabaseWriteLocked = 2; - DatabaseReadLocked = 3; - DatabaseUserDidNotMatch = 4; - DatabaseInternalError = 5; + UserDatabaseInitFailed = 1; + UserDatabaseWriteLocked = 2; + UserDatabaseReadLocked = 3; + UserDatabaseDidNotMatch = 4; + UserDatabaseInternalError = 5; UserNotLoginYet = 10; ReadCurrentIdFailed = 11; WriteCurrentIdFailed = 12; @@ -19,4 +19,5 @@ enum UserErrorCode { UserNameInvalid = 22; UserWorkspaceInvalid = 23; UserIdInvalid = 24; + CreateDefaultWorkspaceFailed = 25; } diff --git a/rust-lib/flowy-user/src/services/user_session/database.rs b/rust-lib/flowy-user/src/services/user_session/database.rs index 135937459b..f286957b99 100644 --- a/rust-lib/flowy-user/src/services/user_session/database.rs +++ b/rust-lib/flowy-user/src/services/user_session/database.rs @@ -1,13 +1,9 @@ use crate::errors::{ErrorBuilder, UserError, UserErrorCode}; use flowy_database::{DBConnection, Database}; use lazy_static::lazy_static; -use std::{ - cell::RefCell, - sync::{ - atomic::{AtomicBool, Ordering}, - RwLock, - }, -}; +use once_cell::sync::Lazy; +use parking_lot::Mutex; +use std::{collections::HashMap, sync::RwLock}; lazy_static! { static ref DB: RwLock> = RwLock::new(None); @@ -25,85 +21,78 @@ impl UserDB { } fn open_user_db(&self, user_id: &str) -> Result<(), UserError> { - INIT_FLAG.store(true, Ordering::SeqCst); + if user_id.is_empty() { + return Err(ErrorBuilder::new(UserErrorCode::UserDatabaseInitFailed) + .msg("user id is empty") + .build()); + } + let dir = format!("{}/{}", self.db_dir, user_id); let db = flowy_database::init(&dir).map_err(|e| { - ErrorBuilder::new(UserErrorCode::DatabaseInitFailed) + log::error!("flowy_database::init failed, {:?}", e); + ErrorBuilder::new(UserErrorCode::UserDatabaseInitFailed) .error(e) .build() })?; - let mut user_db = DB.write().map_err(|e| { - ErrorBuilder::new(UserErrorCode::DatabaseWriteLocked) + let mut db_map = DB_MAP.write().map_err(|e| { + ErrorBuilder::new(UserErrorCode::UserDatabaseWriteLocked) .error(e) .build() })?; - *(user_db) = Some(db); - set_user_id(Some(user_id.to_owned())); + db_map.insert(user_id.to_owned(), db); Ok(()) } - pub(crate) fn close_user_db(&self) -> Result<(), UserError> { - INIT_FLAG.store(false, Ordering::SeqCst); - - let mut write_guard = DB.write().map_err(|e| { - ErrorBuilder::new(UserErrorCode::DatabaseWriteLocked) + pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), UserError> { + let mut db_map = DB_MAP.write().map_err(|e| { + ErrorBuilder::new(UserErrorCode::UserDatabaseWriteLocked) .msg(format!("Close user db failed. {:?}", e)) .build() })?; - - *write_guard = None; - set_user_id(None); - + set_user_db_init(false, user_id); + db_map.remove(user_id); Ok(()) } pub(crate) fn get_connection(&self, user_id: &str) -> Result { - if !INIT_FLAG.load(Ordering::SeqCst) { - let _ = self.open_user_db(user_id); + if !is_user_db_init(user_id) { + let _ = self.open_user_db(user_id)?; + set_user_db_init(true, user_id); } - let thread_user_id = get_user_id(); - if thread_user_id.is_some() { - if thread_user_id != Some(user_id.to_owned()) { - let msg = format!( - "Database owner does not match. origin: {:?}, current: {}", - thread_user_id, user_id - ); - log::error!("{}", msg); - - return Err(ErrorBuilder::new(UserErrorCode::DatabaseUserDidNotMatch) - .msg(msg) - .build()); - } - } - - let read_guard = DB.read().map_err(|e| { - ErrorBuilder::new(UserErrorCode::DatabaseReadLocked) + let db_map = DB_MAP.read().map_err(|e| { + ErrorBuilder::new(UserErrorCode::UserDatabaseReadLocked) .error(e) .build() })?; - match read_guard.as_ref() { - None => Err(ErrorBuilder::new(UserErrorCode::DatabaseInitFailed) - .msg("Database is not initialization") + + match db_map.get(user_id) { + None => Err(ErrorBuilder::new(UserErrorCode::UserDatabaseInitFailed) + .msg("Get connection failed. The database is not initialization") .build()), Some(database) => Ok(database.get_connection()?), } } } -thread_local! { - static USER_ID: RefCell> = RefCell::new(None); +lazy_static! { + static ref DB_MAP: RwLock> = RwLock::new(HashMap::new()); } -fn set_user_id(user_id: Option) { - USER_ID.with(|id| { - *id.borrow_mut() = user_id; - }); -} -fn get_user_id() -> Option { USER_ID.with(|id| id.borrow().clone()) } -static INIT_FLAG: AtomicBool = AtomicBool::new(false); +static INIT_FLAG_MAP: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new())); +fn set_user_db_init(is_init: bool, user_id: &str) { + let mut flag_map = INIT_FLAG_MAP.lock(); + flag_map.insert(user_id.to_owned(), is_init); +} + +fn is_user_db_init(user_id: &str) -> bool { + match INIT_FLAG_MAP.lock().get(user_id) { + None => false, + Some(flag) => flag.clone(), + } +} #[cfg(test)] mod tests { diff --git a/rust-lib/flowy-user/src/services/user_session/user_server.rs b/rust-lib/flowy-user/src/services/user_session/user_server.rs index ef9636adab..ab9085b535 100644 --- a/rust-lib/flowy-user/src/services/user_session/user_server.rs +++ b/rust-lib/flowy-user/src/services/user_session/user_server.rs @@ -1,13 +1,23 @@ use crate::{ entities::{SignInParams, SignUpParams, UserDetail}, - errors::{ErrorBuilder, UserError, UserErrorCode}, - sql_tables::User, + errors::UserError, + sql_tables::UserTable, }; -use flowy_infra::uuid; +use flowy_dispatch::prelude::DispatchFuture; pub trait UserServer { - fn sign_up(&self, params: SignUpParams) -> Result; - fn sign_in(&self, params: SignInParams) -> Result; - fn get_user_info(&self, user_id: &str) -> Result; + fn sign_up(&self, params: SignUpParams) -> Result; + + fn sign_in(&self, params: SignInParams) -> Result; + fn sign_out(&self, user_id: &str) -> Result<(), UserError>; + + fn get_user_info(&self, user_id: &str) -> Result; + + fn create_workspace( + &self, + name: &str, + desc: &str, + user_id: &str, + ) -> DispatchFuture>; } diff --git a/rust-lib/flowy-user/src/services/user_session/user_session.rs b/rust-lib/flowy-user/src/services/user_session/user_session.rs index 97f7fa8d82..a226a3d279 100644 --- a/rust-lib/flowy-user/src/services/user_session/user_session.rs +++ b/rust-lib/flowy-user/src/services/user_session/user_session.rs @@ -6,18 +6,21 @@ use flowy_database::{ UserDatabaseConnection, }; use flowy_infra::kv::KVStore; -use lazy_static::lazy_static; + use std::sync::{Arc, RwLock}; use crate::{ - entities::{SignInParams, SignUpParams, UpdateUserParams, UserDetail}, + entities::{SignInParams, SignUpParams, UpdateUserParams, UpdateUserRequest, UserDetail}, errors::{ErrorBuilder, UserError, UserErrorCode}, - event::UserEvent::GetStatus, + event::UserEvent::*, services::user_session::{database::UserDB, user_server::UserServer}, - sql_tables::{User, UserChangeset}, + sql_tables::{UserTable, UserTableChangeset}, }; -use flowy_dispatch::prelude::{Data, EventDispatch, ModuleRequest}; -use std::convert::TryFrom; +use flowy_dispatch::prelude::{EventDispatch, ModuleRequest, ToBytes}; + +const DEFAULT_WORKSPACE_NAME: &'static str = "My workspace"; +const DEFAULT_WORKSPACE_DESC: &'static str = "This is your first workspace"; +const DEFAULT_WORKSPACE: &'static str = "Default_Workspace"; pub struct UserSessionConfig { root_dir: String, @@ -35,6 +38,7 @@ pub struct UserSession { database: UserDB, config: UserSessionConfig, server: Arc, + user_id: RwLock>, } impl UserSession { @@ -47,23 +51,38 @@ impl UserSession { database: db, config, server, + user_id: RwLock::new(None), } } - pub async fn sign_in(&self, params: SignInParams) -> Result { + pub fn get_db_connection(&self) -> Result { + let user_id = self.get_user_id()?; + self.database.get_connection(&user_id) + } + + pub async fn sign_in(&self, params: SignInParams) -> Result { let user = self.server.sign_in(params)?; - let _ = set_current_user_id(Some(user.id.clone()))?; - self.save_user(user) + let _ = self.set_user_id(Some(user.id.clone()))?; + + let user_table = self.save_user(user)?; + let _ = self + .create_default_workspace_if_need(&user_table.id) + .await?; + Ok(user_table) } - pub async fn sign_up(&self, params: SignUpParams) -> Result { + pub async fn sign_up(&self, params: SignUpParams) -> Result { let user = self.server.sign_up(params)?; - let _ = set_current_user_id(Some(user.id.clone()))?; - self.save_user(user) + let _ = self.set_user_id(Some(user.id.clone()))?; + let user_table = self.save_user(user)?; + let _ = self + .create_default_workspace_if_need(&user_table.id) + .await?; + Ok(user_table) } - pub async fn sign_out(&self) -> Result<(), UserError> { - let user_id = self.current_user_id()?; + pub fn sign_out(&self) -> Result<(), UserError> { + let user_id = self.get_user_id()?; let conn = self.get_db_connection()?; let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&user_id))).execute(&*conn)?; @@ -71,28 +90,35 @@ impl UserSession { Ok(_) => {}, Err(_) => {}, } - let _ = self.database.close_user_db()?; - let _ = set_current_user_id(None)?; + let _ = self.database.close_user_db(&user_id)?; + let _ = self.set_user_id(None)?; Ok(()) } - pub async fn update_user(&self, params: UpdateUserParams) -> Result { - let changeset = UserChangeset::new(params); + fn save_user(&self, user: UserTable) -> Result { + let conn = self.get_db_connection()?; + let _ = diesel::insert_into(user_table::table) + .values(user.clone()) + .execute(&*conn)?; + + Ok(user) + } + + pub fn update_user(&self, params: UpdateUserParams) -> Result { + let changeset = UserTableChangeset::new(params); let conn = self.get_db_connection()?; diesel_update_table!(user_table, changeset, conn); - let user_detail = self.current_user_detail()?; + let user_detail = self.user_detail()?; Ok(user_detail) } - pub fn current_user_detail(&self) -> Result { - let user_id = self.current_user_id()?; - let conn = self.get_db_connection()?; - + pub fn user_detail(&self) -> Result { + let user_id = self.get_user_id()?; let user = dsl::user_table .filter(user_table::id.eq(&user_id)) - .first::(&*conn)?; + .first::(&*(self.get_db_connection()?))?; match self.server.get_user_info(&user_id) { Ok(_user_detail) => { @@ -106,60 +132,78 @@ impl UserSession { Ok(UserDetail::from(user)) } - pub fn get_db_connection(&self) -> Result { - let user_id = get_current_user_id()?; - self.database.get_connection(&user_id) + pub fn set_user_id(&self, user_id: Option) -> Result<(), UserError> { + log::trace!("Set user id: {:?}", user_id); + KVStore::set_str(USER_ID_CACHE_KEY, user_id.clone().unwrap_or("".to_owned())); + match self.user_id.write() { + Ok(mut write_guard) => { + *write_guard = user_id; + Ok(()) + }, + Err(e) => Err(ErrorBuilder::new(UserErrorCode::WriteCurrentIdFailed) + .error(e) + .build()), + } } - pub fn set_current_workspace() { - unimplemented!() + pub fn get_user_id(&self) -> Result { + let mut user_id = { + let read_guard = self.user_id.read().map_err(|e| { + ErrorBuilder::new(UserErrorCode::ReadCurrentIdFailed) + .error(e) + .build() + })?; - // let request = SignInRequest { - // email: valid_email(), - // password: valid_password(), - // }; - // - // let user_detail = Tester::::new(SignIn) - // .request(request) - // .sync_send() - // .parse::(); - // - // user_detail - } + (*read_guard).clone() + }; - #[allow(dead_code)] - pub fn get_current_workspace(&self) -> Result { - // let response = EventDispatch::sync_send(ModuleRequest::new(GetStatus)); - // let user_detail = - // >::try_from(response.payload).unwrap().into_inner(); - let user_id = get_current_user_id()?; - let conn = self.get_db_connection()?; + if user_id.is_none() { + user_id = KVStore::get_str(USER_ID_CACHE_KEY); + let _ = self.set_user_id(user_id.clone())?; + } - let workspace = dsl::user_table - .filter(user_table::id.eq(&user_id)) - .select(user_table::workspace) - .first::(&*conn)?; - - Ok(workspace) - } -} - -impl UserSession { - fn save_user(&self, user: User) -> Result { - let conn = self.get_db_connection()?; - let _ = diesel::insert_into(user_table::table) - .values(user.clone()) - .execute(&*conn)?; - - Ok(user) - } - - fn current_user_id(&self) -> Result { - match KVStore::get_str(USER_ID_DISK_CACHE_KEY) { + match user_id { None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()), Some(user_id) => Ok(user_id), } } + + pub async fn set_current_workspace(&self, workspace_id: &str) -> Result<(), UserError> { + let user_id = self.get_user_id()?; + let payload: Vec = UpdateUserRequest::new(&user_id) + .workspace(workspace_id) + .into_bytes() + .unwrap(); + + let request = ModuleRequest::new(UpdateUser).payload(payload); + let _ = EventDispatch::async_send(request) + .await + .parse::() + .unwrap()?; + Ok(()) + } + + async fn create_default_workspace_if_need(&self, user_id: &str) -> Result<(), UserError> { + let key = format!("{}{}", user_id, DEFAULT_WORKSPACE); + if KVStore::get_bool(&key).unwrap_or(false) { + return Ok(()); + } + + KVStore::set_bool(&key, true); + log::debug!("Create user:{} default workspace", user_id); + let _ = self + .server + .create_workspace(DEFAULT_WORKSPACE_NAME, DEFAULT_WORKSPACE_DESC, user_id) + .await?; + Ok(()) + } +} + +pub fn current_user_id() -> Result { + match KVStore::get_str(USER_ID_CACHE_KEY) { + None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()), + Some(user_id) => Ok(user_id), + } } impl UserDatabaseConnection for UserSession { @@ -168,48 +212,4 @@ impl UserDatabaseConnection for UserSession { } } -const USER_ID_DISK_CACHE_KEY: &str = "user_id"; -lazy_static! { - pub static ref CURRENT_USER_ID: RwLock> = RwLock::new(None); -} - -pub(crate) fn get_current_user_id() -> Result { - let read_guard = CURRENT_USER_ID.read().map_err(|e| { - ErrorBuilder::new(UserErrorCode::ReadCurrentIdFailed) - .error(e) - .build() - })?; - - let mut user_id = (*read_guard).clone(); - // explicitly drop the read_guard in case of dead lock - drop(read_guard); - - if user_id.is_none() { - user_id = KVStore::get_str(USER_ID_DISK_CACHE_KEY); - *(CURRENT_USER_ID.write().unwrap()) = user_id.clone(); - } - - if user_id.is_none() { - return Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()); - } - - match user_id { - None => Err(ErrorBuilder::new(UserErrorCode::UserNotLoginYet).build()), - Some(user_id) => Ok(user_id), - } -} - -pub(crate) fn set_current_user_id(user_id: Option) -> Result<(), UserError> { - KVStore::set_str( - USER_ID_DISK_CACHE_KEY, - user_id.clone().unwrap_or("".to_owned()), - ); - - let mut current_user_id = CURRENT_USER_ID.write().map_err(|e| { - ErrorBuilder::new(UserErrorCode::WriteCurrentIdFailed) - .error(e) - .build() - })?; - *current_user_id = user_id; - Ok(()) -} +const USER_ID_CACHE_KEY: &str = "user_id"; diff --git a/rust-lib/flowy-user/src/sql_tables/user.rs b/rust-lib/flowy-user/src/sql_tables/user.rs index 826837e09d..7b2d7e9b62 100644 --- a/rust-lib/flowy-user/src/sql_tables/user.rs +++ b/rust-lib/flowy-user/src/sql_tables/user.rs @@ -3,7 +3,7 @@ use flowy_database::schema::user_table; #[derive(Clone, Default, Queryable, Identifiable, Insertable)] #[table_name = "user_table"] -pub struct User { +pub struct UserTable { pub(crate) id: String, pub(crate) name: String, pub(crate) password: String, @@ -11,7 +11,7 @@ pub struct User { pub(crate) workspace: String, } -impl User { +impl UserTable { pub fn new(id: String, name: String, email: String, password: String) -> Self { Self { id, @@ -30,7 +30,7 @@ impl User { #[derive(AsChangeset, Identifiable, Default, Debug)] #[table_name = "user_table"] -pub struct UserChangeset { +pub struct UserTableChangeset { pub id: String, pub workspace: Option, pub name: Option, @@ -38,9 +38,9 @@ pub struct UserChangeset { pub password: Option, } -impl UserChangeset { +impl UserTableChangeset { pub fn new(params: UpdateUserParams) -> Self { - UserChangeset { + UserTableChangeset { id: params.id, workspace: params.workspace, name: params.name, diff --git a/rust-lib/flowy-user/tests/event/helper.rs b/rust-lib/flowy-user/tests/event/helper.rs index 0fea574637..ba0d12ece5 100644 --- a/rust-lib/flowy-user/tests/event/helper.rs +++ b/rust-lib/flowy-user/tests/event/helper.rs @@ -1,7 +1,6 @@ -use flowy_test::{TestBuilder, Tester}; -use flowy_user::errors::UserError; +pub use flowy_test::builder::UserTestBuilder; -pub type UserTestBuilder = TestBuilder; +pub use flowy_test::prelude::{random_valid_email, valid_password}; pub(crate) fn invalid_email_test_case() -> Vec { // https://gist.github.com/cjaoude/fd9910626629b53c4d25 @@ -38,8 +37,4 @@ pub(crate) fn invalid_password_test_case() -> Vec { .collect::>() } -pub(crate) fn valid_email() -> String { "annie@appflowy.io".to_string() } - -pub(crate) fn valid_password() -> String { "HelloWorld!123".to_string() } - pub(crate) fn valid_name() -> String { "AppFlowy".to_string() } diff --git a/rust-lib/flowy-user/tests/event/main.rs b/rust-lib/flowy-user/tests/event/main.rs index ce3c9fb1cd..c5c296acab 100644 --- a/rust-lib/flowy-user/tests/event/main.rs +++ b/rust-lib/flowy-user/tests/event/main.rs @@ -1,5 +1,5 @@ mod helper; mod sign_in_test; mod sign_up_test; -mod user_detail_test; mod user_status_test; +mod user_update_test; diff --git a/rust-lib/flowy-user/tests/event/sign_in_test.rs b/rust-lib/flowy-user/tests/event/sign_in_test.rs index 67817f874c..a3a28a33f7 100644 --- a/rust-lib/flowy-user/tests/event/sign_in_test.rs +++ b/rust-lib/flowy-user/tests/event/sign_in_test.rs @@ -1,5 +1,4 @@ use crate::helper::*; - use flowy_user::{errors::UserErrorCode, event::UserEvent::*, prelude::*}; use serial_test::*; @@ -7,7 +6,7 @@ use serial_test::*; #[serial] fn sign_in_success() { let request = SignInRequest { - email: valid_email(), + email: random_valid_email(), password: valid_password(), }; @@ -21,6 +20,7 @@ fn sign_in_success() { } #[test] +#[serial] fn sign_in_with_invalid_email() { for email in invalid_email_test_case() { let request = SignInRequest { @@ -41,10 +41,11 @@ fn sign_in_with_invalid_email() { } #[test] +#[serial] fn sign_in_with_invalid_password() { for password in invalid_password_test_case() { let request = SignInRequest { - email: valid_email(), + email: random_valid_email(), password, }; diff --git a/rust-lib/flowy-user/tests/event/sign_up_test.rs b/rust-lib/flowy-user/tests/event/sign_up_test.rs index e08b5dd061..037ed4a5b0 100644 --- a/rust-lib/flowy-user/tests/event/sign_up_test.rs +++ b/rust-lib/flowy-user/tests/event/sign_up_test.rs @@ -1,27 +1,25 @@ use crate::helper::*; - use flowy_user::{errors::*, event::UserEvent::*, prelude::*}; use serial_test::*; #[test] #[serial] fn sign_up_success() { - let _ = UserTestBuilder::new().event(SignOut).sync_send(); let request = SignUpRequest { - email: valid_email(), + email: random_valid_email(), name: valid_name(), password: valid_password(), }; let _response = UserTestBuilder::new() + .logout() .event(SignUp) .request(request) .sync_send(); - // .parse::(); - // dbg!(&response); } #[test] +#[serial] fn sign_up_with_invalid_email() { for email in invalid_email_test_case() { let request = SignUpRequest { @@ -42,10 +40,11 @@ fn sign_up_with_invalid_email() { } } #[test] +#[serial] fn sign_up_with_invalid_password() { for password in invalid_password_test_case() { let request = SignUpRequest { - email: valid_email(), + email: random_valid_email(), name: valid_name(), password, }; diff --git a/rust-lib/flowy-user/tests/event/user_status_test.rs b/rust-lib/flowy-user/tests/event/user_status_test.rs index 62655f37bc..391a325acd 100644 --- a/rust-lib/flowy-user/tests/event/user_status_test.rs +++ b/rust-lib/flowy-user/tests/event/user_status_test.rs @@ -1,23 +1,22 @@ use crate::helper::*; -use flowy_user::{errors::UserErrorCode, event::UserEvent::*, prelude::*}; +use flowy_user::{event::UserEvent::*, prelude::*}; use serial_test::*; #[test] -#[should_panic] #[serial] fn user_status_get_failed_before_login() { - let _ = UserTestBuilder::new() + let a = UserTestBuilder::new() .logout() .event(GetStatus) - .sync_send() - .parse::(); + .assert_error() + .sync_send(); } #[test] #[serial] fn user_status_get_success_after_login() { let request = SignInRequest { - email: valid_email(), + email: random_valid_email(), password: valid_password(), }; diff --git a/rust-lib/flowy-user/tests/event/user_detail_test.rs b/rust-lib/flowy-user/tests/event/user_update_test.rs similarity index 89% rename from rust-lib/flowy-user/tests/event/user_detail_test.rs rename to rust-lib/flowy-user/tests/event/user_update_test.rs index cd113e4fbf..78c9ca332f 100644 --- a/rust-lib/flowy-user/tests/event/user_detail_test.rs +++ b/rust-lib/flowy-user/tests/event/user_update_test.rs @@ -5,7 +5,7 @@ use serial_test::*; #[test] #[serial] fn user_update_with_name() { - let user_detail = UserTestBuilder::new().login().user_detail.unwrap(); + let user_detail = UserTestBuilder::new().reset().user_detail.unwrap(); let new_name = "hello_world".to_owned(); let request = UpdateUserRequest { id: user_detail.id.clone(), @@ -27,7 +27,7 @@ fn user_update_with_name() { #[test] #[serial] fn user_update_with_email() { - let user_detail = UserTestBuilder::new().login().user_detail.unwrap(); + let user_detail = UserTestBuilder::new().reset().user_detail.unwrap(); let new_email = "123@gmai.com".to_owned(); let request = UpdateUserRequest { id: user_detail.id.clone(), @@ -49,7 +49,7 @@ fn user_update_with_email() { #[test] #[serial] fn user_update_with_password() { - let user_detail = UserTestBuilder::new().login().user_detail.unwrap(); + let user_detail = UserTestBuilder::new().reset().user_detail.unwrap(); let new_password = "H123world!".to_owned(); let request = UpdateUserRequest { id: user_detail.id.clone(), @@ -69,7 +69,7 @@ fn user_update_with_password() { #[test] #[serial] fn user_update_with_invalid_email() { - let user_detail = UserTestBuilder::new().login().user_detail.unwrap(); + let user_detail = UserTestBuilder::new().reset().user_detail.unwrap(); for email in invalid_email_test_case() { let request = UpdateUserRequest { id: user_detail.id.clone(), @@ -94,7 +94,7 @@ fn user_update_with_invalid_email() { #[test] #[serial] fn user_update_with_invalid_password() { - let user_detail = UserTestBuilder::new().login().user_detail.unwrap(); + let user_detail = UserTestBuilder::new().reset().user_detail.unwrap(); for password in invalid_password_test_case() { let request = UpdateUserRequest { id: user_detail.id.clone(), @@ -119,7 +119,7 @@ fn user_update_with_invalid_password() { #[test] #[serial] fn user_update_with_invalid_name() { - let user_detail = UserTestBuilder::new().login().user_detail.unwrap(); + let user_detail = UserTestBuilder::new().reset().user_detail.unwrap(); let request = UpdateUserRequest { id: user_detail.id.clone(), name: Some("".to_string()), diff --git a/rust-lib/flowy-workspace/Cargo.toml b/rust-lib/flowy-workspace/Cargo.toml index 4610dcdcf7..3ec792721b 100644 --- a/rust-lib/flowy-workspace/Cargo.toml +++ b/rust-lib/flowy-workspace/Cargo.toml @@ -16,6 +16,8 @@ protobuf = {version = "2.18.0"} log = "0.4.14" diesel = {version = "1.4.7", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} +futures-core = { version = "0.3", default-features = false } +pin-project = "1.0.0" lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } diff --git a/rust-lib/flowy-workspace/src/entities/app/app_create.rs b/rust-lib/flowy-workspace/src/entities/app/app_create.rs index 5d74537dcb..e4bbba81b2 100644 --- a/rust-lib/flowy-workspace/src/entities/app/app_create.rs +++ b/rust-lib/flowy-workspace/src/entities/app/app_create.rs @@ -41,7 +41,7 @@ impl TryInto for CreateAppRequest { fn try_into(self) -> Result { let name = AppName::parse(self.name).map_err(|e| { - ErrorBuilder::new(WorkspaceErrorCode::WorkspaceNameInvalid) + ErrorBuilder::new(WorkspaceErrorCode::AppNameInvalid) .msg(e) .build() })?; @@ -68,7 +68,7 @@ impl TryInto for CreateAppRequest { } #[derive(ProtoBuf, Default, Debug)] -pub struct AppDetail { +pub struct App { #[pb(index = 1)] pub id: String, diff --git a/rust-lib/flowy-workspace/src/entities/app/mod.rs b/rust-lib/flowy-workspace/src/entities/app/mod.rs index d370d42cd8..3f23b6b562 100644 --- a/rust-lib/flowy-workspace/src/entities/app/mod.rs +++ b/rust-lib/flowy-workspace/src/entities/app/mod.rs @@ -3,4 +3,4 @@ pub use app_update::*; mod app_create; mod app_update; -mod parser; +pub mod parser; diff --git a/rust-lib/flowy-workspace/src/entities/mod.rs b/rust-lib/flowy-workspace/src/entities/mod.rs index 8f9840256b..aae9164e81 100644 --- a/rust-lib/flowy-workspace/src/entities/mod.rs +++ b/rust-lib/flowy-workspace/src/entities/mod.rs @@ -1,2 +1,3 @@ pub mod app; +pub mod view; pub mod workspace; diff --git a/rust-lib/flowy-workspace/src/entities/view/mod.rs b/rust-lib/flowy-workspace/src/entities/view/mod.rs new file mode 100644 index 0000000000..f9768ab8f2 --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/view/mod.rs @@ -0,0 +1,4 @@ +mod parser; +mod view_create; + +pub use view_create::*; diff --git a/rust-lib/flowy-workspace/src/entities/view/parser/mod.rs b/rust-lib/flowy-workspace/src/entities/view/parser/mod.rs new file mode 100644 index 0000000000..088fdf8144 --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/view/parser/mod.rs @@ -0,0 +1,9 @@ +mod view_desc; +mod view_name; +mod view_thumbnail; +mod view_type; + +pub use view_desc::*; +pub use view_name::*; +pub use view_thumbnail::*; +pub use view_type::*; diff --git a/rust-lib/flowy-workspace/src/entities/view/parser/view_desc.rs b/rust-lib/flowy-workspace/src/entities/view/parser/view_desc.rs new file mode 100644 index 0000000000..b3635bc258 --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/view/parser/view_desc.rs @@ -0,0 +1,18 @@ +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct ViewDesc(pub String); + +impl ViewDesc { + pub fn parse(s: String) -> Result { + if s.graphemes(true).count() > 1000 { + return Err(format!("View desc too long")); + } + + Ok(Self(s)) + } +} + +impl AsRef for ViewDesc { + fn as_ref(&self) -> &str { &self.0 } +} diff --git a/rust-lib/flowy-workspace/src/entities/view/parser/view_name.rs b/rust-lib/flowy-workspace/src/entities/view/parser/view_name.rs new file mode 100644 index 0000000000..f283b092ca --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/view/parser/view_name.rs @@ -0,0 +1,22 @@ +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct ViewName(pub String); + +impl ViewName { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(format!("View name can not be empty or whitespace")); + } + + if s.graphemes(true).count() > 256 { + return Err(format!("View name too long")); + } + + Ok(Self(s)) + } +} + +impl AsRef for ViewName { + fn as_ref(&self) -> &str { &self.0 } +} diff --git a/rust-lib/flowy-workspace/src/entities/view/parser/view_thumbnail.rs b/rust-lib/flowy-workspace/src/entities/view/parser/view_thumbnail.rs new file mode 100644 index 0000000000..6fe1aba136 --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/view/parser/view_thumbnail.rs @@ -0,0 +1,20 @@ +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct ViewThumbnail(pub String); + +impl ViewThumbnail { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(format!("View thumbnail can not be empty or whitespace")); + } + + // TODO: verify the thumbnail url is valid or not + + Ok(Self(s)) + } +} + +impl AsRef for ViewThumbnail { + fn as_ref(&self) -> &str { &self.0 } +} diff --git a/rust-lib/flowy-workspace/src/entities/view/parser/view_type.rs b/rust-lib/flowy-workspace/src/entities/view/parser/view_type.rs new file mode 100644 index 0000000000..7486a6bdb5 --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/view/parser/view_type.rs @@ -0,0 +1,13 @@ +use crate::{entities::view::ViewTypeIdentifier, sql_tables::view::ViewType}; +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct ViewTypeCheck(pub ViewType); + +impl ViewTypeCheck { + pub fn parse(s: ViewTypeIdentifier) -> Result { + match s { + ViewTypeIdentifier::Docs => Ok(Self(ViewType::Docs)), + } + } +} diff --git a/rust-lib/flowy-workspace/src/entities/view/view_create.rs b/rust-lib/flowy-workspace/src/entities/view/view_create.rs new file mode 100644 index 0000000000..10b81491b8 --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/view/view_create.rs @@ -0,0 +1,104 @@ +use crate::{ + entities::{app::parser::AppId, view::parser::*}, + errors::{ErrorBuilder, WorkspaceError, WorkspaceErrorCode}, + sql_tables::view::ViewType, +}; +use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use std::convert::TryInto; + +#[derive(Debug, ProtoBuf_Enum)] +pub enum ViewTypeIdentifier { + Docs = 0, +} + +impl std::default::Default for ViewTypeIdentifier { + fn default() -> Self { ViewTypeIdentifier::Docs } +} + +#[derive(Default, ProtoBuf)] +pub struct CreateViewRequest { + #[pb(index = 1)] + pub app_id: String, + + #[pb(index = 2)] + pub name: String, + + #[pb(index = 3)] + pub desc: String, + + #[pb(index = 4, one_of)] + pub thumbnail: Option, + + #[pb(index = 5)] + pub view_type: ViewTypeIdentifier, +} + +pub struct CreateViewParams { + pub app_id: String, + pub name: String, + pub desc: String, + pub thumbnail: String, + pub view_type: ViewType, +} + +impl TryInto for CreateViewRequest { + type Error = WorkspaceError; + + fn try_into(self) -> Result { + let name = ViewName::parse(self.name) + .map_err(|e| { + ErrorBuilder::new(WorkspaceErrorCode::ViewNameInvalid) + .msg(e) + .build() + })? + .0; + + let app_id = AppId::parse(self.app_id) + .map_err(|e| { + ErrorBuilder::new(WorkspaceErrorCode::AppIdInvalid) + .msg(e) + .build() + })? + .0; + + let thumbnail = match self.thumbnail { + None => "".to_string(), + Some(thumbnail) => { + ViewThumbnail::parse(thumbnail) + .map_err(|e| { + ErrorBuilder::new(WorkspaceErrorCode::ViewThumbnailName) + .msg(e) + .build() + })? + .0 + }, + }; + + let view_type = ViewTypeCheck::parse(self.view_type).unwrap().0; + Ok(CreateViewParams { + app_id, + name, + desc: self.desc, + thumbnail, + view_type, + }) + } +} + +#[derive(ProtoBuf, Default, Debug)] +pub struct View { + #[pb(index = 1)] + pub id: String, + + #[pb(index = 2)] + pub app_id: String, + + #[pb(index = 3)] + pub name: String, + + #[pb(index = 4)] + pub desc: String, + + #[pb(index = 5)] + pub view_type: ViewTypeIdentifier, +} diff --git a/rust-lib/flowy-workspace/src/entities/workspace/mod.rs b/rust-lib/flowy-workspace/src/entities/workspace/mod.rs index 8c44c9cd11..39e3f34656 100644 --- a/rust-lib/flowy-workspace/src/entities/workspace/mod.rs +++ b/rust-lib/flowy-workspace/src/entities/workspace/mod.rs @@ -1,8 +1,10 @@ pub use workspace_create::*; pub use workspace_query::*; pub use workspace_update::*; +pub use workspace_user_detail::*; pub(crate) mod parser; mod workspace_create; mod workspace_query; mod workspace_update; +mod workspace_user_detail; diff --git a/rust-lib/flowy-workspace/src/entities/workspace/workspace_create.rs b/rust-lib/flowy-workspace/src/entities/workspace/workspace_create.rs index 8860009192..6a1b4656b7 100644 --- a/rust-lib/flowy-workspace/src/entities/workspace/workspace_create.rs +++ b/rust-lib/flowy-workspace/src/entities/workspace/workspace_create.rs @@ -34,7 +34,7 @@ impl TryInto for CreateWorkspaceRequest { } #[derive(ProtoBuf, Default, Debug)] -pub struct WorkspaceDetail { +pub struct Workspace { #[pb(index = 1)] pub id: String, diff --git a/rust-lib/flowy-workspace/src/entities/workspace/workspace_user_detail.rs b/rust-lib/flowy-workspace/src/entities/workspace/workspace_user_detail.rs new file mode 100644 index 0000000000..5db0639f39 --- /dev/null +++ b/rust-lib/flowy-workspace/src/entities/workspace/workspace_user_detail.rs @@ -0,0 +1,20 @@ +use crate::entities::workspace::Workspace; +use flowy_derive::ProtoBuf; + +#[derive(ProtoBuf, Default, Debug)] +pub struct UserWorkspace { + #[pb(index = 1)] + pub owner: String, + + #[pb(index = 2)] + pub workspace_id: String, +} + +#[derive(ProtoBuf, Default, Debug)] +pub struct UserWorkspaceDetail { + #[pb(index = 1)] + pub owner: String, + + #[pb(index = 2)] + pub workspace: Workspace, +} diff --git a/rust-lib/flowy-workspace/src/errors.rs b/rust-lib/flowy-workspace/src/errors.rs index d9b5d71074..ec8380c2eb 100644 --- a/rust-lib/flowy-workspace/src/errors.rs +++ b/rust-lib/flowy-workspace/src/errors.rs @@ -36,16 +36,28 @@ pub enum WorkspaceErrorCode { AppColorStyleInvalid = 3, #[display(fmt = "App id is invalid")] - AppIdInvalid = 4, + AppIdInvalid = 10, + + #[display(fmt = "App name is invalid")] + AppNameInvalid = 11, + + #[display(fmt = "View name is invalid")] + ViewNameInvalid = 20, + + #[display(fmt = "Thumbnail of the view is invalid")] + ViewThumbnailName = 21, #[display(fmt = "Get database connection failed")] - DatabaseConnectionFail = 5, + DatabaseConnectionFail = 100, #[display(fmt = "Database internal error")] - DatabaseInternalError = 6, + WorkspaceDatabaseError = 101, #[display(fmt = "User internal error")] - UserInternalError = 10, + UserInternalError = 102, + + #[display(fmt = "User not login yet")] + UserNotLoginYet = 103, } impl std::default::Default for WorkspaceErrorCode { @@ -54,15 +66,7 @@ impl std::default::Default for WorkspaceErrorCode { impl std::convert::From for WorkspaceError { fn from(error: flowy_database::result::Error) -> Self { - ErrorBuilder::new(WorkspaceErrorCode::DatabaseInternalError) - .error(error) - .build() - } -} - -impl std::convert::From for WorkspaceError { - fn from(error: flowy_sqlite::Error) -> Self { - ErrorBuilder::new(WorkspaceErrorCode::DatabaseInternalError) + ErrorBuilder::new(WorkspaceErrorCode::WorkspaceDatabaseError) .error(error) .build() } diff --git a/rust-lib/flowy-workspace/src/event.rs b/rust-lib/flowy-workspace/src/event.rs index f19ab12980..fd707f9995 100644 --- a/rust-lib/flowy-workspace/src/event.rs +++ b/rust-lib/flowy-workspace/src/event.rs @@ -6,5 +6,17 @@ use flowy_derive::{Flowy_Event, ProtoBuf_Enum}; pub enum WorkspaceEvent { #[display(fmt = "Create workspace")] #[event(input = "CreateSpaceRequest", output = "WorkspaceDetail")] - CreateWorkspace = 0, + CreateWorkspace = 0, + + #[display(fmt = "Get user's workspace detail")] + #[event(output = "UserWorkspaceDetail")] + GetWorkspaceDetail = 1, + + #[display(fmt = "Create app")] + #[event(input = "CreateAppRequest", output = "App")] + CreateApp = 101, + + #[display(fmt = "Create view")] + #[event(input = "CreateViewRequest", output = "View")] + CreateView = 201, } diff --git a/rust-lib/flowy-workspace/src/handlers/app_handler.rs b/rust-lib/flowy-workspace/src/handlers/app_handler.rs index 72e41a5cbe..0100bffceb 100644 --- a/rust-lib/flowy-workspace/src/handlers/app_handler.rs +++ b/rust-lib/flowy-workspace/src/handlers/app_handler.rs @@ -1,5 +1,5 @@ use crate::{ - entities::app::{AppDetail, CreateAppParams, CreateAppRequest}, + entities::app::{App, CreateAppParams, CreateAppRequest}, errors::WorkspaceError, services::AppController, }; @@ -9,7 +9,7 @@ use std::{convert::TryInto, sync::Arc}; pub async fn create_app( data: Data, controller: ModuleData>, -) -> ResponseResult { +) -> ResponseResult { let params: CreateAppParams = data.into_inner().try_into()?; let detail = controller.save_app(params)?; response_ok(detail) diff --git a/rust-lib/flowy-workspace/src/handlers/mod.rs b/rust-lib/flowy-workspace/src/handlers/mod.rs index fdf08a9b51..95ed7acdcb 100644 --- a/rust-lib/flowy-workspace/src/handlers/mod.rs +++ b/rust-lib/flowy-workspace/src/handlers/mod.rs @@ -1,5 +1,7 @@ mod app_handler; +mod view_handler; mod workspace_handler; pub use app_handler::*; +pub use view_handler::*; pub use workspace_handler::*; diff --git a/rust-lib/flowy-workspace/src/handlers/view_handler.rs b/rust-lib/flowy-workspace/src/handlers/view_handler.rs new file mode 100644 index 0000000000..45510b708b --- /dev/null +++ b/rust-lib/flowy-workspace/src/handlers/view_handler.rs @@ -0,0 +1,16 @@ +use crate::{ + entities::view::{CreateViewParams, CreateViewRequest, View}, + errors::WorkspaceError, + services::ViewController, +}; +use flowy_dispatch::prelude::{response_ok, Data, ModuleData, ResponseResult}; +use std::{convert::TryInto, sync::Arc}; + +pub async fn create_view( + data: Data, + controller: ModuleData>, +) -> ResponseResult { + let params: CreateViewParams = data.into_inner().try_into()?; + let view = controller.save_view(params).await?; + response_ok(view) +} diff --git a/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs b/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs index 4faf654c21..ff73d58abf 100644 --- a/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs +++ b/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs @@ -1,5 +1,11 @@ use crate::{ - entities::workspace::{CreateWorkspaceParams, CreateWorkspaceRequest, WorkspaceDetail}, + entities::workspace::{ + CreateWorkspaceParams, + CreateWorkspaceRequest, + UserWorkspace, + UserWorkspaceDetail, + Workspace, + }, errors::WorkspaceError, services::WorkspaceController, }; @@ -9,8 +15,16 @@ use std::{convert::TryInto, sync::Arc}; pub async fn create_workspace( data: Data, controller: ModuleData>, -) -> ResponseResult { +) -> ResponseResult { + let controller = controller.get_ref().clone(); let params: CreateWorkspaceParams = data.into_inner().try_into()?; - let detail = controller.save_workspace(params)?; + let detail = controller.save_workspace(params).await?; response_ok(detail) } + +pub async fn get_workspace_detail( + controller: ModuleData>, +) -> ResponseResult { + let user_workspace = controller.get_user_workspace_detail().await?; + response_ok(user_workspace) +} diff --git a/rust-lib/flowy-workspace/src/lib.rs b/rust-lib/flowy-workspace/src/lib.rs index 6b5878e12f..111c190399 100644 --- a/rust-lib/flowy-workspace/src/lib.rs +++ b/rust-lib/flowy-workspace/src/lib.rs @@ -13,6 +13,9 @@ mod services; #[macro_use] extern crate flowy_database; +#[macro_use] +extern crate flowy_dispatch; + pub mod prelude { pub use crate::{errors::*, module::*, services::*}; } diff --git a/rust-lib/flowy-workspace/src/macros.rs b/rust-lib/flowy-workspace/src/macros.rs index 4690db7a9e..76431defce 100644 --- a/rust-lib/flowy-workspace/src/macros.rs +++ b/rust-lib/flowy-workspace/src/macros.rs @@ -9,25 +9,7 @@ macro_rules! impl_sql_binary_expression { out: &mut diesel::serialize::Output, ) -> diesel::serialize::Result { let bytes: Vec = self.try_into().map_err(|e| format!("{:?}", e))?; - diesel::serialize::ToSql::< - diesel::sql_types::Binary, - diesel::sqlite::Sqlite, - >::to_sql(&bytes, out) - - // match self.try_into() { - // Ok(bytes) => diesel::serialize::ToSql::< - // diesel::sql_types::Binary, - // diesel::sqlite::Sqlite, - // >::to_sql(&bytes, out), - // Err(e) => { - // log::error!( - // "{:?} serialize to bytes fail. {:?}", - // std::any::type_name::<$target>(), - // e - // ); - // panic!(); - // }, - // } + diesel::serialize::ToSql::::to_sql(&bytes, out) } } // https://docs.diesel.rs/src/diesel/sqlite/types/mod.rs.html#30-33 @@ -64,3 +46,37 @@ macro_rules! impl_sql_binary_expression { } }; } + +#[macro_export] +macro_rules! impl_sql_integer_expression { + ($target:ident) => { + use diesel::{ + deserialize, + deserialize::FromSql, + serialize, + serialize::{Output, ToSql}, + }; + use std::io::Write; + + impl ToSql for $target + where + DB: diesel::backend::Backend, + i32: ToSql, + { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + (*self as i32).to_sql(out) + } + } + + impl FromSql for $target + where + DB: diesel::backend::Backend, + i32: FromSql, + { + fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result { + let smaill_int = i32::from_sql(bytes)?; + Ok($target::from(smaill_int)) + } + } + }; +} diff --git a/rust-lib/flowy-workspace/src/module.rs b/rust-lib/flowy-workspace/src/module.rs index 40c060c060..7d5f7f540e 100644 --- a/rust-lib/flowy-workspace/src/module.rs +++ b/rust-lib/flowy-workspace/src/module.rs @@ -3,25 +3,31 @@ use flowy_dispatch::prelude::*; use crate::{ errors::WorkspaceError, event::WorkspaceEvent, - handlers::create_workspace, services::{AppController, WorkspaceController}, }; -use flowy_database::{DBConnection, UserDatabaseConnection}; +use flowy_database::DBConnection; + +use crate::{entities::workspace::UserWorkspace, handlers::*, services::ViewController}; use std::sync::Arc; pub trait WorkspaceUser: Send + Sync { - fn set_current_workspace(&self, id: &str); - fn get_current_workspace(&self) -> Result; + fn set_cur_workspace_id(&self, id: &str) -> DispatchFuture>; + fn get_cur_workspace(&self) -> DispatchFuture>; fn db_connection(&self) -> Result; } pub fn create(user: Arc) -> Module { let workspace_controller = Arc::new(WorkspaceController::new(user.clone())); let app_controller = Arc::new(AppController::new(user.clone())); + let view_controller = Arc::new(ViewController::new(user.clone())); Module::new() .name("Flowy-Workspace") .data(workspace_controller) .data(app_controller) + .data(view_controller) .event(WorkspaceEvent::CreateWorkspace, create_workspace) + .event(WorkspaceEvent::GetWorkspaceDetail, get_workspace_detail) + .event(WorkspaceEvent::CreateApp, create_app) + .event(WorkspaceEvent::CreateView, create_view) } diff --git a/rust-lib/flowy-workspace/src/protobuf/model/app_create.rs b/rust-lib/flowy-workspace/src/protobuf/model/app_create.rs index 7e9d0986fe..d2dd5814d0 100644 --- a/rust-lib/flowy-workspace/src/protobuf/model/app_create.rs +++ b/rust-lib/flowy-workspace/src/protobuf/model/app_create.rs @@ -483,7 +483,7 @@ impl ::protobuf::reflect::ProtobufValue for ColorStyle { } #[derive(PartialEq,Clone,Default)] -pub struct AppDetail { +pub struct App { // message fields pub id: ::std::string::String, pub workspace_id: ::std::string::String, @@ -494,14 +494,14 @@ pub struct AppDetail { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a AppDetail { - fn default() -> &'a AppDetail { - ::default_instance() +impl<'a> ::std::default::Default for &'a App { + fn default() -> &'a App { + ::default_instance() } } -impl AppDetail { - pub fn new() -> AppDetail { +impl App { + pub fn new() -> App { ::std::default::Default::default() } @@ -610,7 +610,7 @@ impl AppDetail { } } -impl ::protobuf::Message for AppDetail { +impl ::protobuf::Message for App { fn is_initialized(&self) -> bool { true } @@ -703,8 +703,8 @@ impl ::protobuf::Message for AppDetail { Self::descriptor_static() } - fn new() -> AppDetail { - AppDetail::new() + fn new() -> App { + App::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -713,39 +713,39 @@ impl ::protobuf::Message for AppDetail { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "id", - |m: &AppDetail| { &m.id }, - |m: &mut AppDetail| { &mut m.id }, + |m: &App| { &m.id }, + |m: &mut App| { &mut m.id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "workspace_id", - |m: &AppDetail| { &m.workspace_id }, - |m: &mut AppDetail| { &mut m.workspace_id }, + |m: &App| { &m.workspace_id }, + |m: &mut App| { &mut m.workspace_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "name", - |m: &AppDetail| { &m.name }, - |m: &mut AppDetail| { &mut m.name }, + |m: &App| { &m.name }, + |m: &mut App| { &mut m.name }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "desc", - |m: &AppDetail| { &m.desc }, - |m: &mut AppDetail| { &mut m.desc }, + |m: &App| { &m.desc }, + |m: &mut App| { &mut m.desc }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "AppDetail", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "App", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static AppDetail { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(AppDetail::new) + fn default_instance() -> &'static App { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(App::new) } } -impl ::protobuf::Clear for AppDetail { +impl ::protobuf::Clear for App { fn clear(&mut self) { self.id.clear(); self.workspace_id.clear(); @@ -755,13 +755,13 @@ impl ::protobuf::Clear for AppDetail { } } -impl ::std::fmt::Debug for AppDetail { +impl ::std::fmt::Debug for App { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for AppDetail { +impl ::protobuf::reflect::ProtobufValue for App { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -772,39 +772,39 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ce_id\x18\x01\x20\x01(\tR\x0bworkspaceId\x12\x12\n\x04name\x18\x02\x20\ \x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12,\n\ \x0bcolor_style\x18\x04\x20\x01(\x0b2\x0b.ColorStyleR\ncolorStyle\"-\n\n\ - ColorStyle\x12\x1f\n\x0btheme_color\x18\x01\x20\x01(\tR\nthemeColor\"f\n\ - \tAppDetail\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12!\n\x0cworkspac\ - e_id\x18\x02\x20\x01(\tR\x0bworkspaceId\x12\x12\n\x04name\x18\x03\x20\ - \x01(\tR\x04name\x12\x12\n\x04desc\x18\x04\x20\x01(\tR\x04descJ\xc9\x04\ - \n\x06\x12\x04\0\0\x10\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\ - \0\x12\x04\x02\0\x07\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x18\n\x0b\n\ - \x04\x04\0\x02\0\x12\x03\x03\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\ - \x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\ - \x04\0\x02\0\x03\x12\x03\x03\x1a\x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\ - \x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\ - \x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\ - \x03\x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\ - \x05\x04\0\x02\x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\ - \x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\ - \x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x1f\n\x0c\n\x05\x04\0\x02\x03\ - \x06\x12\x03\x06\x04\x0e\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06\x0f\ - \x1a\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x1d\x1e\n\n\n\x02\x04\x01\ - \x12\x04\x08\0\n\x01\n\n\n\x03\x04\x01\x01\x12\x03\x08\x08\x12\n\x0b\n\ - \x04\x04\x01\x02\0\x12\x03\t\x04\x1b\n\x0c\n\x05\x04\x01\x02\0\x05\x12\ - \x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\t\x0b\x16\n\x0c\n\x05\ - \x04\x01\x02\0\x03\x12\x03\t\x19\x1a\n\n\n\x02\x04\x02\x12\x04\x0b\0\x10\ - \x01\n\n\n\x03\x04\x02\x01\x12\x03\x0b\x08\x11\n\x0b\n\x04\x04\x02\x02\0\ - \x12\x03\x0c\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0c\x04\n\n\ - \x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0c\x0b\r\n\x0c\n\x05\x04\x02\x02\0\ - \x03\x12\x03\x0c\x10\x11\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\r\x04\x1c\n\ - \x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\r\x04\n\n\x0c\n\x05\x04\x02\x02\ - \x01\x01\x12\x03\r\x0b\x17\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\r\x1a\ - \x1b\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x0e\x04\x14\n\x0c\n\x05\x04\x02\ - \x02\x02\x05\x12\x03\x0e\x04\n\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\ - \x0e\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x0e\x12\x13\n\x0b\n\ - \x04\x04\x02\x02\x03\x12\x03\x0f\x04\x14\n\x0c\n\x05\x04\x02\x02\x03\x05\ - \x12\x03\x0f\x04\n\n\x0c\n\x05\x04\x02\x02\x03\x01\x12\x03\x0f\x0b\x0f\n\ - \x0c\n\x05\x04\x02\x02\x03\x03\x12\x03\x0f\x12\x13b\x06proto3\ + ColorStyle\x12\x1f\n\x0btheme_color\x18\x01\x20\x01(\tR\nthemeColor\"`\n\ + \x03App\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12!\n\x0cworkspace_id\ + \x18\x02\x20\x01(\tR\x0bworkspaceId\x12\x12\n\x04name\x18\x03\x20\x01(\t\ + R\x04name\x12\x12\n\x04desc\x18\x04\x20\x01(\tR\x04descJ\xc9\x04\n\x06\ + \x12\x04\0\0\x10\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\ + \x04\x02\0\x07\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x18\n\x0b\n\x04\ + \x04\0\x02\0\x12\x03\x03\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\ + \x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\x04\0\ + \x02\0\x03\x12\x03\x03\x1a\x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\ + \x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\ + \x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\ + \x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\ + \x04\0\x02\x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\ + \x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\x0b\ + \n\x04\x04\0\x02\x03\x12\x03\x06\x04\x1f\n\x0c\n\x05\x04\0\x02\x03\x06\ + \x12\x03\x06\x04\x0e\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06\x0f\x1a\n\ + \x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x1d\x1e\n\n\n\x02\x04\x01\x12\ + \x04\x08\0\n\x01\n\n\n\x03\x04\x01\x01\x12\x03\x08\x08\x12\n\x0b\n\x04\ + \x04\x01\x02\0\x12\x03\t\x04\x1b\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\t\ + \x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\t\x0b\x16\n\x0c\n\x05\x04\ + \x01\x02\0\x03\x12\x03\t\x19\x1a\n\n\n\x02\x04\x02\x12\x04\x0b\0\x10\x01\ + \n\n\n\x03\x04\x02\x01\x12\x03\x0b\x08\x0b\n\x0b\n\x04\x04\x02\x02\0\x12\ + \x03\x0c\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0c\x04\n\n\x0c\n\ + \x05\x04\x02\x02\0\x01\x12\x03\x0c\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\ + \x12\x03\x0c\x10\x11\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\r\x04\x1c\n\x0c\ + \n\x05\x04\x02\x02\x01\x05\x12\x03\r\x04\n\n\x0c\n\x05\x04\x02\x02\x01\ + \x01\x12\x03\r\x0b\x17\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\r\x1a\x1b\ + \n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x0e\x04\x14\n\x0c\n\x05\x04\x02\x02\ + \x02\x05\x12\x03\x0e\x04\n\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x0e\ + \x0b\x0f\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x0e\x12\x13\n\x0b\n\x04\ + \x04\x02\x02\x03\x12\x03\x0f\x04\x14\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\ + \x03\x0f\x04\n\n\x0c\n\x05\x04\x02\x02\x03\x01\x12\x03\x0f\x0b\x0f\n\x0c\ + \n\x05\x04\x02\x02\x03\x03\x12\x03\x0f\x12\x13b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/rust-lib/flowy-workspace/src/protobuf/model/errors.rs b/rust-lib/flowy-workspace/src/protobuf/model/errors.rs index 2ac71808cd..8e9695898d 100644 --- a/rust-lib/flowy-workspace/src/protobuf/model/errors.rs +++ b/rust-lib/flowy-workspace/src/protobuf/model/errors.rs @@ -219,10 +219,14 @@ pub enum WorkspaceErrorCode { WorkspaceNameInvalid = 1, WorkspaceIdInvalid = 2, AppColorStyleInvalid = 3, - AppIdInvalid = 4, - DatabaseConnectionFail = 5, - DatabaseInternalError = 6, - UserInternalError = 10, + AppIdInvalid = 10, + AppNameInvalid = 11, + ViewNameInvalid = 20, + ViewThumbnailName = 21, + DatabaseConnectionFail = 100, + WorkspaceDatabaseError = 101, + UserInternalError = 102, + UserNotLoginYet = 103, } impl ::protobuf::ProtobufEnum for WorkspaceErrorCode { @@ -236,10 +240,14 @@ impl ::protobuf::ProtobufEnum for WorkspaceErrorCode { 1 => ::std::option::Option::Some(WorkspaceErrorCode::WorkspaceNameInvalid), 2 => ::std::option::Option::Some(WorkspaceErrorCode::WorkspaceIdInvalid), 3 => ::std::option::Option::Some(WorkspaceErrorCode::AppColorStyleInvalid), - 4 => ::std::option::Option::Some(WorkspaceErrorCode::AppIdInvalid), - 5 => ::std::option::Option::Some(WorkspaceErrorCode::DatabaseConnectionFail), - 6 => ::std::option::Option::Some(WorkspaceErrorCode::DatabaseInternalError), - 10 => ::std::option::Option::Some(WorkspaceErrorCode::UserInternalError), + 10 => ::std::option::Option::Some(WorkspaceErrorCode::AppIdInvalid), + 11 => ::std::option::Option::Some(WorkspaceErrorCode::AppNameInvalid), + 20 => ::std::option::Option::Some(WorkspaceErrorCode::ViewNameInvalid), + 21 => ::std::option::Option::Some(WorkspaceErrorCode::ViewThumbnailName), + 100 => ::std::option::Option::Some(WorkspaceErrorCode::DatabaseConnectionFail), + 101 => ::std::option::Option::Some(WorkspaceErrorCode::WorkspaceDatabaseError), + 102 => ::std::option::Option::Some(WorkspaceErrorCode::UserInternalError), + 103 => ::std::option::Option::Some(WorkspaceErrorCode::UserNotLoginYet), _ => ::std::option::Option::None } } @@ -251,9 +259,13 @@ impl ::protobuf::ProtobufEnum for WorkspaceErrorCode { WorkspaceErrorCode::WorkspaceIdInvalid, WorkspaceErrorCode::AppColorStyleInvalid, WorkspaceErrorCode::AppIdInvalid, + WorkspaceErrorCode::AppNameInvalid, + WorkspaceErrorCode::ViewNameInvalid, + WorkspaceErrorCode::ViewThumbnailName, WorkspaceErrorCode::DatabaseConnectionFail, - WorkspaceErrorCode::DatabaseInternalError, + WorkspaceErrorCode::WorkspaceDatabaseError, WorkspaceErrorCode::UserInternalError, + WorkspaceErrorCode::UserNotLoginYet, ]; values } @@ -284,36 +296,46 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceErrorCode { static file_descriptor_proto_data: &'static [u8] = b"\ \n\x0cerrors.proto\"K\n\x0eWorkspaceError\x12'\n\x04code\x18\x01\x20\x01\ (\x0e2\x13.WorkspaceErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\ - \tR\x03msg*\xcd\x01\n\x12WorkspaceErrorCode\x12\x0b\n\x07Unknown\x10\0\ + \tR\x03msg*\xa3\x02\n\x12WorkspaceErrorCode\x12\x0b\n\x07Unknown\x10\0\ \x12\x18\n\x14WorkspaceNameInvalid\x10\x01\x12\x16\n\x12WorkspaceIdInval\ id\x10\x02\x12\x18\n\x14AppColorStyleInvalid\x10\x03\x12\x10\n\x0cAppIdI\ - nvalid\x10\x04\x12\x1a\n\x16DatabaseConnectionFail\x10\x05\x12\x19\n\x15\ - DatabaseInternalError\x10\x06\x12\x15\n\x11UserInternalError\x10\nJ\xf8\ - \x03\n\x06\x12\x04\0\0\x0f\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\ - \x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x16\n\ - \x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x20\n\x0c\n\x05\x04\0\x02\0\x06\ - \x12\x03\x03\x04\x16\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x17\x1b\n\ - \x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x1e\x1f\n\x0b\n\x04\x04\0\x02\x01\ - \x12\x03\x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\ - \x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\ - \x01\x03\x12\x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x0f\x01\n\n\n\ - \x03\x05\0\x01\x12\x03\x06\x05\x17\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\ - \x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\x05\ - \0\x02\0\x02\x12\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\ - \x04\x1d\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x18\n\x0c\n\x05\ - \x05\0\x02\x01\x02\x12\x03\x08\x1b\x1c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\ - \t\x04\x1b\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x16\n\x0c\n\x05\ - \x05\0\x02\x02\x02\x12\x03\t\x19\x1a\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\ - \x04\x1d\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x18\n\x0c\n\x05\x05\ - \0\x02\x03\x02\x12\x03\n\x1b\x1c\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\ - \x04\x15\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x10\n\x0c\n\x05\ - \x05\0\x02\x04\x02\x12\x03\x0b\x13\x14\n\x0b\n\x04\x05\0\x02\x05\x12\x03\ - \x0c\x04\x1f\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x1a\n\x0c\n\ - \x05\x05\0\x02\x05\x02\x12\x03\x0c\x1d\x1e\n\x0b\n\x04\x05\0\x02\x06\x12\ - \x03\r\x04\x1e\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x19\n\x0c\n\ - \x05\x05\0\x02\x06\x02\x12\x03\r\x1c\x1d\n\x0b\n\x04\x05\0\x02\x07\x12\ - \x03\x0e\x04\x1b\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x15\n\x0c\ - \n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x18\x1ab\x06proto3\ + nvalid\x10\n\x12\x12\n\x0eAppNameInvalid\x10\x0b\x12\x13\n\x0fViewNameIn\ + valid\x10\x14\x12\x15\n\x11ViewThumbnailName\x10\x15\x12\x1a\n\x16Databa\ + seConnectionFail\x10d\x12\x1a\n\x16WorkspaceDatabaseError\x10e\x12\x15\n\ + \x11UserInternalError\x10f\x12\x13\n\x0fUserNotLoginYet\x10gJ\x9c\x05\n\ + \x06\x12\x04\0\0\x13\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\ + \x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x16\n\x0b\n\ + \x04\x04\0\x02\0\x12\x03\x03\x04\x20\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\ + \x03\x04\x16\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x17\x1b\n\x0c\n\x05\ + \x04\0\x02\0\x03\x12\x03\x03\x1e\x1f\n\x0b\n\x04\x04\0\x02\x01\x12\x03\ + \x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\ + \x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\ + \x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x13\x01\n\n\n\x03\x05\0\ + \x01\x12\x03\x06\x05\x17\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\x04\x10\n\ + \x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x0b\n\x0c\n\x05\x05\0\x02\0\ + \x02\x12\x03\x07\x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x1d\n\ + \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x18\n\x0c\n\x05\x05\0\x02\ + \x01\x02\x12\x03\x08\x1b\x1c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x1b\ + \n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x16\n\x0c\n\x05\x05\0\x02\ + \x02\x02\x12\x03\t\x19\x1a\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\x04\x1d\n\ + \x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x18\n\x0c\n\x05\x05\0\x02\x03\ + \x02\x12\x03\n\x1b\x1c\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\x04\x16\n\ + \x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x10\n\x0c\n\x05\x05\0\x02\ + \x04\x02\x12\x03\x0b\x13\x15\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x0c\x04\ + \x18\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04\x12\n\x0c\n\x05\x05\0\ + \x02\x05\x02\x12\x03\x0c\x15\x17\n\x0b\n\x04\x05\0\x02\x06\x12\x03\r\x04\ + \x19\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x13\n\x0c\n\x05\x05\0\ + \x02\x06\x02\x12\x03\r\x16\x18\n\x0b\n\x04\x05\0\x02\x07\x12\x03\x0e\x04\ + \x1b\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x15\n\x0c\n\x05\x05\0\ + \x02\x07\x02\x12\x03\x0e\x18\x1a\n\x0b\n\x04\x05\0\x02\x08\x12\x03\x0f\ + \x04!\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x1a\n\x0c\n\x05\x05\ + \0\x02\x08\x02\x12\x03\x0f\x1d\x20\n\x0b\n\x04\x05\0\x02\t\x12\x03\x10\ + \x04!\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x04\x1a\n\x0c\n\x05\x05\0\ + \x02\t\x02\x12\x03\x10\x1d\x20\n\x0b\n\x04\x05\0\x02\n\x12\x03\x11\x04\ + \x1c\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\x15\n\x0c\n\x05\x05\0\ + \x02\n\x02\x12\x03\x11\x18\x1b\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x12\x04\ + \x1a\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\x05\0\ + \x02\x0b\x02\x12\x03\x12\x16\x19b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/rust-lib/flowy-workspace/src/protobuf/model/event.rs b/rust-lib/flowy-workspace/src/protobuf/model/event.rs index 07e5844a3c..efc2005564 100644 --- a/rust-lib/flowy-workspace/src/protobuf/model/event.rs +++ b/rust-lib/flowy-workspace/src/protobuf/model/event.rs @@ -26,6 +26,9 @@ #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum WorkspaceEvent { CreateWorkspace = 0, + GetWorkspaceDetail = 1, + CreateApp = 101, + CreateView = 201, } impl ::protobuf::ProtobufEnum for WorkspaceEvent { @@ -36,6 +39,9 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent { fn from_i32(value: i32) -> ::std::option::Option { match value { 0 => ::std::option::Option::Some(WorkspaceEvent::CreateWorkspace), + 1 => ::std::option::Option::Some(WorkspaceEvent::GetWorkspaceDetail), + 101 => ::std::option::Option::Some(WorkspaceEvent::CreateApp), + 201 => ::std::option::Option::Some(WorkspaceEvent::CreateView), _ => ::std::option::Option::None } } @@ -43,6 +49,9 @@ impl ::protobuf::ProtobufEnum for WorkspaceEvent { fn values() -> &'static [Self] { static values: &'static [WorkspaceEvent] = &[ WorkspaceEvent::CreateWorkspace, + WorkspaceEvent::GetWorkspaceDetail, + WorkspaceEvent::CreateApp, + WorkspaceEvent::CreateView, ]; values } @@ -71,12 +80,19 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0bevent.proto*%\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorkspace\x10\ - \0JS\n\x06\x12\x04\0\0\x04\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\ - \x05\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x13\n\ - \x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x18\n\x0c\n\x05\x05\0\x02\0\x01\ - \x12\x03\x03\x04\x13\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x16\x17b\ - \x06proto3\ + \n\x0bevent.proto*]\n\x0eWorkspaceEvent\x12\x13\n\x0fCreateWorkspace\x10\ + \0\x12\x16\n\x12GetWorkspaceDetail\x10\x01\x12\r\n\tCreateApp\x10e\x12\ + \x0f\n\nCreateView\x10\xc9\x01J\xce\x01\n\x06\x12\x04\0\0\x07\x01\n\x08\ + \n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x07\x01\n\n\n\ + \x03\x05\0\x01\x12\x03\x02\x05\x13\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\ + \x04\x18\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x13\n\x0c\n\x05\x05\ + \0\x02\0\x02\x12\x03\x03\x16\x17\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\ + \x04\x1b\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\x16\n\x0c\n\x05\ + \x05\0\x02\x01\x02\x12\x03\x04\x19\x1a\n\x0b\n\x04\x05\0\x02\x02\x12\x03\ + \x05\x04\x14\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\r\n\x0c\n\x05\ + \x05\0\x02\x02\x02\x12\x03\x05\x10\x13\n\x0b\n\x04\x05\0\x02\x03\x12\x03\ + \x06\x04\x15\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x0e\n\x0c\n\ + \x05\x05\0\x02\x03\x02\x12\x03\x06\x11\x14b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/rust-lib/flowy-workspace/src/protobuf/model/mod.rs b/rust-lib/flowy-workspace/src/protobuf/model/mod.rs index ed856a9b17..27e3001c33 100644 --- a/rust-lib/flowy-workspace/src/protobuf/model/mod.rs +++ b/rust-lib/flowy-workspace/src/protobuf/model/mod.rs @@ -12,6 +12,12 @@ pub use app_create::*; mod event; pub use event::*; +mod view_create; +pub use view_create::*; + +mod workspace_user_detail; +pub use workspace_user_detail::*; + mod workspace_create; pub use workspace_create::*; diff --git a/rust-lib/flowy-workspace/src/protobuf/model/view_create.rs b/rust-lib/flowy-workspace/src/protobuf/model/view_create.rs new file mode 100644 index 0000000000..48a0c8f5e8 --- /dev/null +++ b/rust-lib/flowy-workspace/src/protobuf/model/view_create.rs @@ -0,0 +1,803 @@ +// This file is generated by rust-protobuf 2.22.1. Do not edit +// @generated + +// https://github.com/rust-lang/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy::all)] + +#![allow(unused_attributes)] +#![cfg_attr(rustfmt, rustfmt::skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unused_imports)] +#![allow(unused_results)] +//! Generated file from `view_create.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; + +#[derive(PartialEq,Clone,Default)] +pub struct CreateViewRequest { + // message fields + pub app_id: ::std::string::String, + pub name: ::std::string::String, + pub desc: ::std::string::String, + pub view_type: ViewTypeIdentifier, + // message oneof groups + pub one_of_thumbnail: ::std::option::Option, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a CreateViewRequest { + fn default() -> &'a CreateViewRequest { + ::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum CreateViewRequest_oneof_one_of_thumbnail { + thumbnail(::std::string::String), +} + +impl CreateViewRequest { + pub fn new() -> CreateViewRequest { + ::std::default::Default::default() + } + + // string app_id = 1; + + + pub fn get_app_id(&self) -> &str { + &self.app_id + } + pub fn clear_app_id(&mut self) { + self.app_id.clear(); + } + + // Param is passed by value, moved + pub fn set_app_id(&mut self, v: ::std::string::String) { + self.app_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_app_id(&mut self) -> &mut ::std::string::String { + &mut self.app_id + } + + // Take field + pub fn take_app_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.app_id, ::std::string::String::new()) + } + + // string name = 2; + + + pub fn get_name(&self) -> &str { + &self.name + } + pub fn clear_name(&mut self) { + self.name.clear(); + } + + // Param is passed by value, moved + pub fn set_name(&mut self, v: ::std::string::String) { + self.name = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_name(&mut self) -> &mut ::std::string::String { + &mut self.name + } + + // Take field + pub fn take_name(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.name, ::std::string::String::new()) + } + + // string desc = 3; + + + pub fn get_desc(&self) -> &str { + &self.desc + } + pub fn clear_desc(&mut self) { + self.desc.clear(); + } + + // Param is passed by value, moved + pub fn set_desc(&mut self, v: ::std::string::String) { + self.desc = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_desc(&mut self) -> &mut ::std::string::String { + &mut self.desc + } + + // Take field + pub fn take_desc(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.desc, ::std::string::String::new()) + } + + // string thumbnail = 4; + + + pub fn get_thumbnail(&self) -> &str { + match self.one_of_thumbnail { + ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(ref v)) => v, + _ => "", + } + } + pub fn clear_thumbnail(&mut self) { + self.one_of_thumbnail = ::std::option::Option::None; + } + + pub fn has_thumbnail(&self) -> bool { + match self.one_of_thumbnail { + ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_thumbnail(&mut self, v: ::std::string::String) { + self.one_of_thumbnail = ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(v)) + } + + // Mutable pointer to the field. + pub fn mut_thumbnail(&mut self) -> &mut ::std::string::String { + if let ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(_)) = self.one_of_thumbnail { + } else { + self.one_of_thumbnail = ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(::std::string::String::new())); + } + match self.one_of_thumbnail { + ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_thumbnail(&mut self) -> ::std::string::String { + if self.has_thumbnail() { + match self.one_of_thumbnail.take() { + ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(v)) => v, + _ => panic!(), + } + } else { + ::std::string::String::new() + } + } + + // .ViewTypeIdentifier view_type = 5; + + + pub fn get_view_type(&self) -> ViewTypeIdentifier { + self.view_type + } + pub fn clear_view_type(&mut self) { + self.view_type = ViewTypeIdentifier::Docs; + } + + // Param is passed by value, moved + pub fn set_view_type(&mut self, v: ViewTypeIdentifier) { + self.view_type = v; + } +} + +impl ::protobuf::Message for CreateViewRequest { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.app_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.desc)?; + }, + 4 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_thumbnail = ::std::option::Option::Some(CreateViewRequest_oneof_one_of_thumbnail::thumbnail(is.read_string()?)); + }, + 5 => { + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.app_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.app_id); + } + if !self.name.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.name); + } + if !self.desc.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.desc); + } + if self.view_type != ViewTypeIdentifier::Docs { + my_size += ::protobuf::rt::enum_size(5, self.view_type); + } + if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { + match v { + &CreateViewRequest_oneof_one_of_thumbnail::thumbnail(ref v) => { + my_size += ::protobuf::rt::string_size(4, &v); + }, + }; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.app_id.is_empty() { + os.write_string(1, &self.app_id)?; + } + if !self.name.is_empty() { + os.write_string(2, &self.name)?; + } + if !self.desc.is_empty() { + os.write_string(3, &self.desc)?; + } + if self.view_type != ViewTypeIdentifier::Docs { + os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; + } + if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { + match v { + &CreateViewRequest_oneof_one_of_thumbnail::thumbnail(ref v) => { + os.write_string(4, v)?; + }, + }; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> CreateViewRequest { + CreateViewRequest::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "app_id", + |m: &CreateViewRequest| { &m.app_id }, + |m: &mut CreateViewRequest| { &mut m.app_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "name", + |m: &CreateViewRequest| { &m.name }, + |m: &mut CreateViewRequest| { &mut m.name }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "desc", + |m: &CreateViewRequest| { &m.desc }, + |m: &mut CreateViewRequest| { &mut m.desc }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( + "thumbnail", + CreateViewRequest::has_thumbnail, + CreateViewRequest::get_thumbnail, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "view_type", + |m: &CreateViewRequest| { &m.view_type }, + |m: &mut CreateViewRequest| { &mut m.view_type }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "CreateViewRequest", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static CreateViewRequest { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(CreateViewRequest::new) + } +} + +impl ::protobuf::Clear for CreateViewRequest { + fn clear(&mut self) { + self.app_id.clear(); + self.name.clear(); + self.desc.clear(); + self.one_of_thumbnail = ::std::option::Option::None; + self.view_type = ViewTypeIdentifier::Docs; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for CreateViewRequest { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for CreateViewRequest { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct View { + // message fields + pub id: ::std::string::String, + pub app_id: ::std::string::String, + pub name: ::std::string::String, + pub desc: ::std::string::String, + pub view_type: ViewTypeIdentifier, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a View { + fn default() -> &'a View { + ::default_instance() + } +} + +impl View { + pub fn new() -> View { + ::std::default::Default::default() + } + + // string id = 1; + + + pub fn get_id(&self) -> &str { + &self.id + } + pub fn clear_id(&mut self) { + self.id.clear(); + } + + // Param is passed by value, moved + pub fn set_id(&mut self, v: ::std::string::String) { + self.id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_id(&mut self) -> &mut ::std::string::String { + &mut self.id + } + + // Take field + pub fn take_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.id, ::std::string::String::new()) + } + + // string app_id = 2; + + + pub fn get_app_id(&self) -> &str { + &self.app_id + } + pub fn clear_app_id(&mut self) { + self.app_id.clear(); + } + + // Param is passed by value, moved + pub fn set_app_id(&mut self, v: ::std::string::String) { + self.app_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_app_id(&mut self) -> &mut ::std::string::String { + &mut self.app_id + } + + // Take field + pub fn take_app_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.app_id, ::std::string::String::new()) + } + + // string name = 3; + + + pub fn get_name(&self) -> &str { + &self.name + } + pub fn clear_name(&mut self) { + self.name.clear(); + } + + // Param is passed by value, moved + pub fn set_name(&mut self, v: ::std::string::String) { + self.name = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_name(&mut self) -> &mut ::std::string::String { + &mut self.name + } + + // Take field + pub fn take_name(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.name, ::std::string::String::new()) + } + + // string desc = 4; + + + pub fn get_desc(&self) -> &str { + &self.desc + } + pub fn clear_desc(&mut self) { + self.desc.clear(); + } + + // Param is passed by value, moved + pub fn set_desc(&mut self, v: ::std::string::String) { + self.desc = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_desc(&mut self) -> &mut ::std::string::String { + &mut self.desc + } + + // Take field + pub fn take_desc(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.desc, ::std::string::String::new()) + } + + // .ViewTypeIdentifier view_type = 5; + + + pub fn get_view_type(&self) -> ViewTypeIdentifier { + self.view_type + } + pub fn clear_view_type(&mut self) { + self.view_type = ViewTypeIdentifier::Docs; + } + + // Param is passed by value, moved + pub fn set_view_type(&mut self, v: ViewTypeIdentifier) { + self.view_type = v; + } +} + +impl ::protobuf::Message for View { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.app_id)?; + }, + 3 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.name)?; + }, + 4 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.desc)?; + }, + 5 => { + ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.id); + } + if !self.app_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.app_id); + } + if !self.name.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.name); + } + if !self.desc.is_empty() { + my_size += ::protobuf::rt::string_size(4, &self.desc); + } + if self.view_type != ViewTypeIdentifier::Docs { + my_size += ::protobuf::rt::enum_size(5, self.view_type); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.id.is_empty() { + os.write_string(1, &self.id)?; + } + if !self.app_id.is_empty() { + os.write_string(2, &self.app_id)?; + } + if !self.name.is_empty() { + os.write_string(3, &self.name)?; + } + if !self.desc.is_empty() { + os.write_string(4, &self.desc)?; + } + if self.view_type != ViewTypeIdentifier::Docs { + os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> View { + View::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "id", + |m: &View| { &m.id }, + |m: &mut View| { &mut m.id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "app_id", + |m: &View| { &m.app_id }, + |m: &mut View| { &mut m.app_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "name", + |m: &View| { &m.name }, + |m: &mut View| { &mut m.name }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "desc", + |m: &View| { &m.desc }, + |m: &mut View| { &mut m.desc }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + "view_type", + |m: &View| { &m.view_type }, + |m: &mut View| { &mut m.view_type }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "View", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static View { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(View::new) + } +} + +impl ::protobuf::Clear for View { + fn clear(&mut self) { + self.id.clear(); + self.app_id.clear(); + self.name.clear(); + self.desc.clear(); + self.view_type = ViewTypeIdentifier::Docs; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for View { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for View { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(Clone,PartialEq,Eq,Debug,Hash)] +pub enum ViewTypeIdentifier { + Docs = 0, +} + +impl ::protobuf::ProtobufEnum for ViewTypeIdentifier { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(ViewTypeIdentifier::Docs), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [ViewTypeIdentifier] = &[ + ViewTypeIdentifier::Docs, + ]; + values + } + + fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + ::protobuf::reflect::EnumDescriptor::new_pb_name::("ViewTypeIdentifier", file_descriptor_proto()) + }) + } +} + +impl ::std::marker::Copy for ViewTypeIdentifier { +} + +impl ::std::default::Default for ViewTypeIdentifier { + fn default() -> Self { + ViewTypeIdentifier::Docs + } +} + +impl ::protobuf::reflect::ProtobufValue for ViewTypeIdentifier { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x11view_create.proto\"\xb8\x01\n\x11CreateViewRequest\x12\x15\n\x06ap\ + p_id\x18\x01\x20\x01(\tR\x05appId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\ + \x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\tthumbn\ + ail\x18\x04\x20\x01(\tH\0R\tthumbnail\x120\n\tview_type\x18\x05\x20\x01(\ + \x0e2\x13.ViewTypeIdentifierR\x08viewTypeB\x12\n\x10one_of_thumbnail\"\ + \x87\x01\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x15\n\ + \x06app_id\x18\x02\x20\x01(\tR\x05appId\x12\x12\n\x04name\x18\x03\x20\ + \x01(\tR\x04name\x12\x12\n\x04desc\x18\x04\x20\x01(\tR\x04desc\x120\n\tv\ + iew_type\x18\x05\x20\x01(\x0e2\x13.ViewTypeIdentifierR\x08viewType*\x1e\ + \n\x12ViewTypeIdentifier\x12\x08\n\x04Docs\x10\0J\xc4\x05\n\x06\x12\x04\ + \0\0\x12\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\ + \0\x08\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\x04\x04\0\x02\ + \0\x12\x03\x03\x04\x16\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\ + \x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x11\n\x0c\n\x05\x04\0\x02\0\ + \x03\x12\x03\x03\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x14\n\ + \x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\ + \x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x12\ + \x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\x04\0\x02\ + \x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\ + \x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\x0b\n\x04\x04\0\ + \x08\0\x12\x03\x06\x044\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x06\n\x1a\n\ + \x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x1d2\n\x0c\n\x05\x04\0\x02\x03\x05\ + \x12\x03\x06\x1d#\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06$-\n\x0c\n\ + \x05\x04\0\x02\x03\x03\x12\x03\x0601\n\x0b\n\x04\x04\0\x02\x04\x12\x03\ + \x07\x04%\n\x0c\n\x05\x04\0\x02\x04\x06\x12\x03\x07\x04\x16\n\x0c\n\x05\ + \x04\0\x02\x04\x01\x12\x03\x07\x17\x20\n\x0c\n\x05\x04\0\x02\x04\x03\x12\ + \x03\x07#$\n\n\n\x02\x04\x01\x12\x04\t\0\x0f\x01\n\n\n\x03\x04\x01\x01\ + \x12\x03\t\x08\x0c\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\x12\n\x0c\n\ + \x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\ + \x03\n\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x10\x11\n\x0b\n\x04\ + \x04\x01\x02\x01\x12\x03\x0b\x04\x16\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\ + \x03\x0b\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x0b\x0b\x11\n\x0c\ + \n\x05\x04\x01\x02\x01\x03\x12\x03\x0b\x14\x15\n\x0b\n\x04\x04\x01\x02\ + \x02\x12\x03\x0c\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0c\x04\ + \n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x0c\x0b\x0f\n\x0c\n\x05\x04\ + \x01\x02\x02\x03\x12\x03\x0c\x12\x13\n\x0b\n\x04\x04\x01\x02\x03\x12\x03\ + \r\x04\x14\n\x0c\n\x05\x04\x01\x02\x03\x05\x12\x03\r\x04\n\n\x0c\n\x05\ + \x04\x01\x02\x03\x01\x12\x03\r\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x03\x03\ + \x12\x03\r\x12\x13\n\x0b\n\x04\x04\x01\x02\x04\x12\x03\x0e\x04%\n\x0c\n\ + \x05\x04\x01\x02\x04\x06\x12\x03\x0e\x04\x16\n\x0c\n\x05\x04\x01\x02\x04\ + \x01\x12\x03\x0e\x17\x20\n\x0c\n\x05\x04\x01\x02\x04\x03\x12\x03\x0e#$\n\ + \n\n\x02\x05\0\x12\x04\x10\0\x12\x01\n\n\n\x03\x05\0\x01\x12\x03\x10\x05\ + \x17\n\x0b\n\x04\x05\0\x02\0\x12\x03\x11\x04\r\n\x0c\n\x05\x05\0\x02\0\ + \x01\x12\x03\x11\x04\x08\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x11\x0b\x0c\ + b\x06proto3\ +"; + +static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; + +fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { + ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap() +} + +pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + file_descriptor_proto_lazy.get(|| { + parse_descriptor_proto() + }) +} diff --git a/rust-lib/flowy-workspace/src/protobuf/model/workspace_create.rs b/rust-lib/flowy-workspace/src/protobuf/model/workspace_create.rs index dd34c7851c..1022d2eabf 100644 --- a/rust-lib/flowy-workspace/src/protobuf/model/workspace_create.rs +++ b/rust-lib/flowy-workspace/src/protobuf/model/workspace_create.rs @@ -225,7 +225,7 @@ impl ::protobuf::reflect::ProtobufValue for CreateWorkspaceRequest { } #[derive(PartialEq,Clone,Default)] -pub struct WorkspaceDetail { +pub struct Workspace { // message fields pub id: ::std::string::String, pub name: ::std::string::String, @@ -235,14 +235,14 @@ pub struct WorkspaceDetail { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a WorkspaceDetail { - fn default() -> &'a WorkspaceDetail { - ::default_instance() +impl<'a> ::std::default::Default for &'a Workspace { + fn default() -> &'a Workspace { + ::default_instance() } } -impl WorkspaceDetail { - pub fn new() -> WorkspaceDetail { +impl Workspace { + pub fn new() -> Workspace { ::std::default::Default::default() } @@ -325,7 +325,7 @@ impl WorkspaceDetail { } } -impl ::protobuf::Message for WorkspaceDetail { +impl ::protobuf::Message for Workspace { fn is_initialized(&self) -> bool { true } @@ -409,8 +409,8 @@ impl ::protobuf::Message for WorkspaceDetail { Self::descriptor_static() } - fn new() -> WorkspaceDetail { - WorkspaceDetail::new() + fn new() -> Workspace { + Workspace::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -419,34 +419,34 @@ impl ::protobuf::Message for WorkspaceDetail { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "id", - |m: &WorkspaceDetail| { &m.id }, - |m: &mut WorkspaceDetail| { &mut m.id }, + |m: &Workspace| { &m.id }, + |m: &mut Workspace| { &mut m.id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "name", - |m: &WorkspaceDetail| { &m.name }, - |m: &mut WorkspaceDetail| { &mut m.name }, + |m: &Workspace| { &m.name }, + |m: &mut Workspace| { &mut m.name }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "desc", - |m: &WorkspaceDetail| { &m.desc }, - |m: &mut WorkspaceDetail| { &mut m.desc }, + |m: &Workspace| { &m.desc }, + |m: &mut Workspace| { &mut m.desc }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "WorkspaceDetail", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "Workspace", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static WorkspaceDetail { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(WorkspaceDetail::new) + fn default_instance() -> &'static Workspace { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(Workspace::new) } } -impl ::protobuf::Clear for WorkspaceDetail { +impl ::protobuf::Clear for Workspace { fn clear(&mut self) { self.id.clear(); self.name.clear(); @@ -455,13 +455,13 @@ impl ::protobuf::Clear for WorkspaceDetail { } } -impl ::std::fmt::Debug for WorkspaceDetail { +impl ::std::fmt::Debug for Workspace { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for WorkspaceDetail { +impl ::protobuf::reflect::ProtobufValue for Workspace { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -470,26 +470,26 @@ impl ::protobuf::reflect::ProtobufValue for WorkspaceDetail { static file_descriptor_proto_data: &'static [u8] = b"\ \n\x16workspace_create.proto\"@\n\x16CreateWorkspaceRequest\x12\x12\n\ \x04name\x18\x01\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x02\x20\x01(\ - \tR\x04desc\"I\n\x0fWorkspaceDetail\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\ - \x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\ - \x18\x03\x20\x01(\tR\x04descJ\xd5\x02\n\x06\x12\x04\0\0\n\x01\n\x08\n\ - \x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\ - \x04\0\x01\x12\x03\x02\x08\x1e\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\ - \x14\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\ - \0\x01\x12\x03\x03\x0b\x0f\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x12\ - \x13\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\ - \x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\ - \x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x12\x13\n\n\n\x02\x04\x01\ - \x12\x04\x06\0\n\x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\x17\n\x0b\n\ - \x04\x04\x01\x02\0\x12\x03\x07\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\ - \x03\x07\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\ - \x05\x04\x01\x02\0\x03\x12\x03\x07\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\ - \x12\x03\x08\x04\x14\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x08\x04\n\n\ - \x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\ - \x02\x01\x03\x12\x03\x08\x12\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\t\ - \x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\ - \x01\x02\x02\x01\x12\x03\t\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\ - \x03\t\x12\x13b\x06proto3\ + \tR\x04desc\"C\n\tWorkspace\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\ + \x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\ + \x20\x01(\tR\x04descJ\xd5\x02\n\x06\x12\x04\0\0\n\x01\n\x08\n\x01\x0c\ + \x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\ + \x01\x12\x03\x02\x08\x1e\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x14\n\ + \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\ + \x12\x03\x03\x0b\x0f\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x12\x13\n\ + \x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\x01\ + \x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\x0f\ + \n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x12\x13\n\n\n\x02\x04\x01\x12\ + \x04\x06\0\n\x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\x11\n\x0b\n\x04\ + \x04\x01\x02\0\x12\x03\x07\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\ + \x07\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\ + \x04\x01\x02\0\x03\x12\x03\x07\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\ + \x03\x08\x04\x14\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x08\x04\n\n\x0c\ + \n\x05\x04\x01\x02\x01\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\x02\ + \x01\x03\x12\x03\x08\x12\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\t\x04\ + \x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\ + \x02\x02\x01\x12\x03\t\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\t\ + \x12\x13b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/rust-lib/flowy-workspace/src/protobuf/model/workspace_user_detail.rs b/rust-lib/flowy-workspace/src/protobuf/model/workspace_user_detail.rs new file mode 100644 index 0000000000..ca06200372 --- /dev/null +++ b/rust-lib/flowy-workspace/src/protobuf/model/workspace_user_detail.rs @@ -0,0 +1,476 @@ +// This file is generated by rust-protobuf 2.22.1. Do not edit +// @generated + +// https://github.com/rust-lang/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy::all)] + +#![allow(unused_attributes)] +#![cfg_attr(rustfmt, rustfmt::skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unused_imports)] +#![allow(unused_results)] +//! Generated file from `workspace_user_detail.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; + +#[derive(PartialEq,Clone,Default)] +pub struct UserWorkspace { + // message fields + pub owner: ::std::string::String, + pub workspace_id: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a UserWorkspace { + fn default() -> &'a UserWorkspace { + ::default_instance() + } +} + +impl UserWorkspace { + pub fn new() -> UserWorkspace { + ::std::default::Default::default() + } + + // string owner = 1; + + + pub fn get_owner(&self) -> &str { + &self.owner + } + pub fn clear_owner(&mut self) { + self.owner.clear(); + } + + // Param is passed by value, moved + pub fn set_owner(&mut self, v: ::std::string::String) { + self.owner = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_owner(&mut self) -> &mut ::std::string::String { + &mut self.owner + } + + // Take field + pub fn take_owner(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.owner, ::std::string::String::new()) + } + + // string workspace_id = 2; + + + pub fn get_workspace_id(&self) -> &str { + &self.workspace_id + } + pub fn clear_workspace_id(&mut self) { + self.workspace_id.clear(); + } + + // Param is passed by value, moved + pub fn set_workspace_id(&mut self, v: ::std::string::String) { + self.workspace_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_workspace_id(&mut self) -> &mut ::std::string::String { + &mut self.workspace_id + } + + // Take field + pub fn take_workspace_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.workspace_id, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for UserWorkspace { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.owner)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.workspace_id)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.owner.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.owner); + } + if !self.workspace_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.workspace_id); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.owner.is_empty() { + os.write_string(1, &self.owner)?; + } + if !self.workspace_id.is_empty() { + os.write_string(2, &self.workspace_id)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> UserWorkspace { + UserWorkspace::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "owner", + |m: &UserWorkspace| { &m.owner }, + |m: &mut UserWorkspace| { &mut m.owner }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "workspace_id", + |m: &UserWorkspace| { &m.workspace_id }, + |m: &mut UserWorkspace| { &mut m.workspace_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "UserWorkspace", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static UserWorkspace { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(UserWorkspace::new) + } +} + +impl ::protobuf::Clear for UserWorkspace { + fn clear(&mut self) { + self.owner.clear(); + self.workspace_id.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for UserWorkspace { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for UserWorkspace { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct UserWorkspaceDetail { + // message fields + pub owner: ::std::string::String, + pub workspace: ::protobuf::SingularPtrField, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a UserWorkspaceDetail { + fn default() -> &'a UserWorkspaceDetail { + ::default_instance() + } +} + +impl UserWorkspaceDetail { + pub fn new() -> UserWorkspaceDetail { + ::std::default::Default::default() + } + + // string owner = 1; + + + pub fn get_owner(&self) -> &str { + &self.owner + } + pub fn clear_owner(&mut self) { + self.owner.clear(); + } + + // Param is passed by value, moved + pub fn set_owner(&mut self, v: ::std::string::String) { + self.owner = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_owner(&mut self) -> &mut ::std::string::String { + &mut self.owner + } + + // Take field + pub fn take_owner(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.owner, ::std::string::String::new()) + } + + // .Workspace workspace = 2; + + + pub fn get_workspace(&self) -> &super::workspace_create::Workspace { + self.workspace.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_workspace(&mut self) { + self.workspace.clear(); + } + + pub fn has_workspace(&self) -> bool { + self.workspace.is_some() + } + + // Param is passed by value, moved + pub fn set_workspace(&mut self, v: super::workspace_create::Workspace) { + self.workspace = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_workspace(&mut self) -> &mut super::workspace_create::Workspace { + if self.workspace.is_none() { + self.workspace.set_default(); + } + self.workspace.as_mut().unwrap() + } + + // Take field + pub fn take_workspace(&mut self) -> super::workspace_create::Workspace { + self.workspace.take().unwrap_or_else(|| super::workspace_create::Workspace::new()) + } +} + +impl ::protobuf::Message for UserWorkspaceDetail { + fn is_initialized(&self) -> bool { + for v in &self.workspace { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.owner)?; + }, + 2 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.workspace)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.owner.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.owner); + } + if let Some(ref v) = self.workspace.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.owner.is_empty() { + os.write_string(1, &self.owner)?; + } + if let Some(ref v) = self.workspace.as_ref() { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> UserWorkspaceDetail { + UserWorkspaceDetail::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "owner", + |m: &UserWorkspaceDetail| { &m.owner }, + |m: &mut UserWorkspaceDetail| { &mut m.owner }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "workspace", + |m: &UserWorkspaceDetail| { &m.workspace }, + |m: &mut UserWorkspaceDetail| { &mut m.workspace }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "UserWorkspaceDetail", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static UserWorkspaceDetail { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(UserWorkspaceDetail::new) + } +} + +impl ::protobuf::Clear for UserWorkspaceDetail { + fn clear(&mut self) { + self.owner.clear(); + self.workspace.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for UserWorkspaceDetail { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for UserWorkspaceDetail { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x1bworkspace_user_detail.proto\x1a\x16workspace_create.proto\"H\n\rUs\ + erWorkspace\x12\x14\n\x05owner\x18\x01\x20\x01(\tR\x05owner\x12!\n\x0cwo\ + rkspace_id\x18\x02\x20\x01(\tR\x0bworkspaceId\"U\n\x13UserWorkspaceDetai\ + l\x12\x14\n\x05owner\x18\x01\x20\x01(\tR\x05owner\x12(\n\tworkspace\x18\ + \x02\x20\x01(\x0b2\n.WorkspaceR\tworkspaceJ\xa9\x02\n\x06\x12\x04\0\0\n\ + \x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\x01\0\x20\n\ + \n\n\x02\x04\0\x12\x04\x03\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\x03\x08\ + \x15\n\x0b\n\x04\x04\0\x02\0\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\x02\0\ + \x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x04\x0b\x10\n\ + \x0c\n\x05\x04\0\x02\0\x03\x12\x03\x04\x13\x14\n\x0b\n\x04\x04\0\x02\x01\ + \x12\x03\x05\x04\x1c\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x05\x04\n\n\ + \x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x05\x0b\x17\n\x0c\n\x05\x04\0\x02\ + \x01\x03\x12\x03\x05\x1a\x1b\n\n\n\x02\x04\x01\x12\x04\x07\0\n\x01\n\n\n\ + \x03\x04\x01\x01\x12\x03\x07\x08\x1b\n\x0b\n\x04\x04\x01\x02\0\x12\x03\ + \x08\x04\x15\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x08\x04\n\n\x0c\n\x05\ + \x04\x01\x02\0\x01\x12\x03\x08\x0b\x10\n\x0c\n\x05\x04\x01\x02\0\x03\x12\ + \x03\x08\x13\x14\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\t\x04\x1c\n\x0c\n\ + \x05\x04\x01\x02\x01\x06\x12\x03\t\x04\r\n\x0c\n\x05\x04\x01\x02\x01\x01\ + \x12\x03\t\x0e\x17\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\t\x1a\x1bb\ + \x06proto3\ +"; + +static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; + +fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { + ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap() +} + +pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + file_descriptor_proto_lazy.get(|| { + parse_descriptor_proto() + }) +} diff --git a/rust-lib/flowy-workspace/src/protobuf/proto/app_create.proto b/rust-lib/flowy-workspace/src/protobuf/proto/app_create.proto index fdb1591a26..10c585b344 100644 --- a/rust-lib/flowy-workspace/src/protobuf/proto/app_create.proto +++ b/rust-lib/flowy-workspace/src/protobuf/proto/app_create.proto @@ -9,7 +9,7 @@ message CreateAppRequest { message ColorStyle { string theme_color = 1; } -message AppDetail { +message App { string id = 1; string workspace_id = 2; string name = 3; diff --git a/rust-lib/flowy-workspace/src/protobuf/proto/errors.proto b/rust-lib/flowy-workspace/src/protobuf/proto/errors.proto index bab7a7c5e8..32ed650635 100644 --- a/rust-lib/flowy-workspace/src/protobuf/proto/errors.proto +++ b/rust-lib/flowy-workspace/src/protobuf/proto/errors.proto @@ -9,8 +9,12 @@ enum WorkspaceErrorCode { WorkspaceNameInvalid = 1; WorkspaceIdInvalid = 2; AppColorStyleInvalid = 3; - AppIdInvalid = 4; - DatabaseConnectionFail = 5; - DatabaseInternalError = 6; - UserInternalError = 10; + AppIdInvalid = 10; + AppNameInvalid = 11; + ViewNameInvalid = 20; + ViewThumbnailName = 21; + DatabaseConnectionFail = 100; + WorkspaceDatabaseError = 101; + UserInternalError = 102; + UserNotLoginYet = 103; } diff --git a/rust-lib/flowy-workspace/src/protobuf/proto/event.proto b/rust-lib/flowy-workspace/src/protobuf/proto/event.proto index 1b4bcac07f..42274c9a32 100644 --- a/rust-lib/flowy-workspace/src/protobuf/proto/event.proto +++ b/rust-lib/flowy-workspace/src/protobuf/proto/event.proto @@ -2,4 +2,7 @@ syntax = "proto3"; enum WorkspaceEvent { CreateWorkspace = 0; + GetWorkspaceDetail = 1; + CreateApp = 101; + CreateView = 201; } diff --git a/rust-lib/flowy-workspace/src/protobuf/proto/view_create.proto b/rust-lib/flowy-workspace/src/protobuf/proto/view_create.proto new file mode 100644 index 0000000000..00d2868e63 --- /dev/null +++ b/rust-lib/flowy-workspace/src/protobuf/proto/view_create.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +message CreateViewRequest { + string app_id = 1; + string name = 2; + string desc = 3; + oneof one_of_thumbnail { string thumbnail = 4; }; + ViewTypeIdentifier view_type = 5; +} +message View { + string id = 1; + string app_id = 2; + string name = 3; + string desc = 4; + ViewTypeIdentifier view_type = 5; +} +enum ViewTypeIdentifier { + Docs = 0; +} diff --git a/rust-lib/flowy-workspace/src/protobuf/proto/workspace_create.proto b/rust-lib/flowy-workspace/src/protobuf/proto/workspace_create.proto index 24a35cc49f..0712daf539 100644 --- a/rust-lib/flowy-workspace/src/protobuf/proto/workspace_create.proto +++ b/rust-lib/flowy-workspace/src/protobuf/proto/workspace_create.proto @@ -4,7 +4,7 @@ message CreateWorkspaceRequest { string name = 1; string desc = 2; } -message WorkspaceDetail { +message Workspace { string id = 1; string name = 2; string desc = 3; diff --git a/rust-lib/flowy-workspace/src/protobuf/proto/workspace_user_detail.proto b/rust-lib/flowy-workspace/src/protobuf/proto/workspace_user_detail.proto new file mode 100644 index 0000000000..c43aed0503 --- /dev/null +++ b/rust-lib/flowy-workspace/src/protobuf/proto/workspace_user_detail.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +import "workspace_create.proto"; + +message UserWorkspace { + string owner = 1; + string workspace_id = 2; +} +message UserWorkspaceDetail { + string owner = 1; + Workspace workspace = 2; +} diff --git a/rust-lib/flowy-workspace/src/services/app_controller.rs b/rust-lib/flowy-workspace/src/services/app_controller.rs index cfa5327574..16a2526e92 100644 --- a/rust-lib/flowy-workspace/src/services/app_controller.rs +++ b/rust-lib/flowy-workspace/src/services/app_controller.rs @@ -1,5 +1,5 @@ use crate::{ - entities::app::{AppDetail, CreateAppParams, *}, + entities::app::{App, CreateAppParams, *}, errors::*, module::WorkspaceUser, sql_tables::app::*, @@ -14,19 +14,19 @@ pub struct AppController { impl AppController { pub fn new(user: Arc) -> Self { Self { user } } - pub fn save_app(&self, params: CreateAppParams) -> Result { - let app = App::new(params); + pub fn save_app(&self, params: CreateAppParams) -> Result { + let app_table = AppTable::new(params); let conn = self.user.db_connection()?; - let detail: AppDetail = app.clone().into(); + let app: App = app_table.clone().into(); let _ = diesel::insert_into(app_table::table) - .values(app) + .values(app_table) .execute(&*conn)?; - Ok(detail) + Ok(app) } pub fn update_app(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> { - let changeset = AppChangeset::new(params); + let changeset = AppTableChangeset::new(params); let conn = self.user.db_connection()?; diesel_update_table!(app_table, changeset, conn); Ok(()) diff --git a/rust-lib/flowy-workspace/src/services/mod.rs b/rust-lib/flowy-workspace/src/services/mod.rs index 0743fa6d23..35c19c299e 100644 --- a/rust-lib/flowy-workspace/src/services/mod.rs +++ b/rust-lib/flowy-workspace/src/services/mod.rs @@ -1,7 +1,9 @@ mod app_controller; mod database; mod helper; +mod view_controller; mod workspace_controller; pub use app_controller::*; +pub use view_controller::*; pub use workspace_controller::*; diff --git a/rust-lib/flowy-workspace/src/services/view_controller.rs b/rust-lib/flowy-workspace/src/services/view_controller.rs new file mode 100644 index 0000000000..2c0507a04e --- /dev/null +++ b/rust-lib/flowy-workspace/src/services/view_controller.rs @@ -0,0 +1,28 @@ +use crate::{ + entities::view::{CreateViewParams, View}, + errors::WorkspaceError, + module::WorkspaceUser, + sql_tables::view::ViewTable, +}; +use flowy_database::{prelude::*, schema::view_table}; +use std::sync::Arc; + +pub struct ViewController { + user: Arc, +} + +impl ViewController { + pub fn new(user: Arc) -> Self { Self { user } } + + pub async fn save_view(&self, params: CreateViewParams) -> Result { + let view_table = ViewTable::new(params); + let conn = self.user.db_connection()?; + let view: View = view_table.clone().into(); + + let _ = diesel::insert_into(view_table::table) + .values(view_table) + .execute(&*conn)?; + + Ok(view) + } +} diff --git a/rust-lib/flowy-workspace/src/services/workspace_controller.rs b/rust-lib/flowy-workspace/src/services/workspace_controller.rs index 568cdc06bd..0356cea43b 100644 --- a/rust-lib/flowy-workspace/src/services/workspace_controller.rs +++ b/rust-lib/flowy-workspace/src/services/workspace_controller.rs @@ -1,36 +1,66 @@ use crate::{entities::workspace::*, errors::*, module::WorkspaceUser, sql_tables::workspace::*}; use flowy_database::{prelude::*, schema::workspace_table}; + +use flowy_database::schema::workspace_table::dsl; +use flowy_dispatch::prelude::DispatchFuture; use std::sync::Arc; pub struct WorkspaceController { - pub(crate) user: Arc, + pub user: Arc, } impl WorkspaceController { pub fn new(user: Arc) -> Self { Self { user } } - pub fn save_workspace( + pub async fn save_workspace( &self, params: CreateWorkspaceParams, - ) -> Result { - let workspace = Workspace::new(params); - let conn = self.user.db_connection()?; - let detail: WorkspaceDetail = workspace.clone().into(); + ) -> Result { + let workspace_table = WorkspaceTable::new(params); + let detail: Workspace = workspace_table.clone().into(); let _ = diesel::insert_into(workspace_table::table) - .values(workspace) - .execute(&*conn)?; + .values(workspace_table) + .execute(&*(self.user.db_connection()?))?; - self.user.set_current_workspace(&detail.id); + let _ = self.user.set_cur_workspace_id(&detail.id).await?; Ok(detail) } + pub fn get_workspace( + &self, + workspace_id: &str, + ) -> DispatchFuture> { + let user = self.user.clone(); + let workspace_id = workspace_id.to_owned(); + DispatchFuture { + fut: Box::pin(async move { + let workspace = dsl::workspace_table + .filter(workspace_table::id.eq(&workspace_id)) + .first::(&*(user.db_connection()?))?; + + // TODO: fetch workspace from remote server + Ok(workspace) + }), + } + } + pub fn update_workspace(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> { - let changeset = WorkspaceChangeset::new(params); + let changeset = WorkspaceTableChangeset::new(params); let conn = self.user.db_connection()?; diesel_update_table!(workspace_table, changeset, conn); Ok(()) } + + pub async fn get_user_workspace_detail(&self) -> Result { + let user_workspace = self.user.get_cur_workspace().await?; + let workspace = self.get_workspace(&user_workspace.workspace_id).await?; + + Ok(UserWorkspaceDetail { + owner: user_workspace.owner, + workspace: workspace.into(), + }) + } } diff --git a/rust-lib/flowy-workspace/src/sql_tables/app/app.rs b/rust-lib/flowy-workspace/src/sql_tables/app/app.rs index 1354fad323..ea5f4080d7 100644 --- a/rust-lib/flowy-workspace/src/sql_tables/app/app.rs +++ b/rust-lib/flowy-workspace/src/sql_tables/app/app.rs @@ -1,7 +1,7 @@ use crate::{ - entities::app::{AppDetail, ColorStyle, CreateAppParams, UpdateAppParams}, + entities::app::{App, ColorStyle, CreateAppParams, UpdateAppParams}, impl_sql_binary_expression, - sql_tables::workspace::Workspace, + sql_tables::workspace::WorkspaceTable, }; use diesel::sql_types::Binary; use flowy_database::schema::app_table; @@ -9,21 +9,10 @@ use flowy_infra::{timestamp, uuid}; use serde::{Deserialize, Serialize, __private::TryFrom}; use std::convert::TryInto; -#[derive( - PartialEq, - Serialize, - Deserialize, - Clone, - Debug, - Queryable, - Identifiable, - Insertable, - Associations, -)] -#[belongs_to(Workspace, foreign_key = "workspace_id")] +#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] +#[belongs_to(WorkspaceTable, foreign_key = "workspace_id")] #[table_name = "app_table"] -#[serde(tag = "type")] -pub(crate) struct App { +pub(crate) struct AppTable { pub id: String, pub workspace_id: String, // equal to #[belongs_to(Workspace, foreign_key = "workspace_id")]. pub name: String, @@ -35,7 +24,7 @@ pub(crate) struct App { pub version: i64, } -impl App { +impl AppTable { pub fn new(params: CreateAppParams) -> Self { let app_id = uuid(); let time = timestamp(); @@ -87,16 +76,16 @@ impl_sql_binary_expression!(ColorStyleCol); #[derive(AsChangeset, Identifiable, Default, Debug)] #[table_name = "app_table"] -pub struct AppChangeset { +pub struct AppTableChangeset { pub id: String, pub workspace_id: Option, pub name: Option, pub desc: Option, } -impl AppChangeset { +impl AppTableChangeset { pub fn new(params: UpdateAppParams) -> Self { - AppChangeset { + AppTableChangeset { id: params.app_id, workspace_id: params.workspace_id, name: params.name, @@ -105,9 +94,9 @@ impl AppChangeset { } } -impl std::convert::Into for App { - fn into(self) -> AppDetail { - AppDetail { +impl std::convert::Into for AppTable { + fn into(self) -> App { + App { id: self.id, workspace_id: self.workspace_id, name: self.name, diff --git a/rust-lib/flowy-workspace/src/sql_tables/view/view.rs b/rust-lib/flowy-workspace/src/sql_tables/view/view.rs index e69de29bb2..0557fe884b 100644 --- a/rust-lib/flowy-workspace/src/sql_tables/view/view.rs +++ b/rust-lib/flowy-workspace/src/sql_tables/view/view.rs @@ -0,0 +1,106 @@ +use crate::{ + entities::view::{CreateViewParams, View, ViewTypeIdentifier}, + impl_sql_integer_expression, + sql_tables::app::AppTable, +}; +use diesel::sql_types::Integer; +use flowy_database::schema::{view_table, view_table::dsl}; +use flowy_infra::{timestamp, uuid}; + +#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] +#[belongs_to(AppTable, foreign_key = "app_id")] +#[table_name = "view_table"] +pub(crate) struct ViewTable { + pub id: String, + pub app_id: String, + pub name: String, + pub desc: String, + pub modified_time: i64, + pub create_time: i64, + pub thumbnail: String, + pub view_type: ViewType, + pub version: i64, +} + +impl ViewTable { + pub fn new(params: CreateViewParams) -> Self { + let view_id = uuid(); + let time = timestamp(); + ViewTable { + id: view_id, + app_id: params.app_id, + name: params.name, + desc: params.desc, + modified_time: time, + create_time: time, + thumbnail: params.thumbnail, + view_type: params.view_type, + version: 0, + } + } +} + +impl std::convert::Into for ViewTable { + fn into(self) -> View { + let view_type = match self.view_type { + ViewType::Docs => ViewTypeIdentifier::Docs, + }; + + View { + id: self.id, + app_id: self.app_id, + name: self.name, + desc: self.desc, + view_type, + } + } +} + +#[derive(AsChangeset, Identifiable, Clone, Default, Debug)] +#[table_name = "view_table"] +pub struct ViewTableChangeset { + pub id: String, + pub name: Option, + pub desc: Option, + pub modified_time: i64, +} + +impl ViewTableChangeset { + pub fn new(id: &str) -> Self { + ViewTableChangeset { + id: id.to_string(), + name: None, + desc: None, + modified_time: timestamp(), + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)] +#[repr(i32)] +#[sql_type = "Integer"] +pub enum ViewType { + Docs = 0, +} + +impl std::default::Default for ViewType { + fn default() -> Self { ViewType::Docs } +} + +impl std::convert::From for ViewType { + fn from(value: i32) -> Self { + match value { + 0 => ViewType::Docs, + o => { + log::error!("Unsupported view type {}, fallback to ViewType::Docs", o); + ViewType::Docs + }, + } + } +} + +impl ViewType { + pub fn value(&self) -> i32 { *self as i32 } +} + +impl_sql_integer_expression!(ViewType); diff --git a/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace.rs b/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace.rs index 5ec20f2c20..5fb3e20ec8 100644 --- a/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace.rs +++ b/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace.rs @@ -1,12 +1,10 @@ -use crate::entities::workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceDetail}; +use crate::entities::workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, Workspace}; use flowy_database::schema::workspace_table; use flowy_infra::{timestamp, uuid}; -use serde::{Deserialize, Serialize}; -#[derive(PartialEq, Clone, Serialize, Deserialize, Debug, Queryable, Identifiable, Insertable)] +#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable)] #[table_name = "workspace_table"] -#[serde(tag = "type")] -pub struct Workspace { +pub struct WorkspaceTable { pub id: String, pub name: String, pub desc: String, @@ -16,20 +14,20 @@ pub struct Workspace { pub version: i64, } -impl Workspace { +impl WorkspaceTable { #[allow(dead_code)] pub fn new(params: CreateWorkspaceParams) -> Self { - let mut workspace = Workspace::default(); + let mut workspace = WorkspaceTable::default(); workspace.name = params.name; workspace.desc = params.desc; workspace } } -impl std::default::Default for Workspace { +impl std::default::Default for WorkspaceTable { fn default() -> Self { let time = timestamp(); - Workspace { + WorkspaceTable { id: uuid(), name: String::default(), desc: String::default(), @@ -43,15 +41,15 @@ impl std::default::Default for Workspace { #[derive(AsChangeset, Identifiable, Clone, Default, Debug)] #[table_name = "workspace_table"] -pub struct WorkspaceChangeset { +pub struct WorkspaceTableChangeset { pub id: String, pub name: Option, pub desc: Option, } -impl WorkspaceChangeset { +impl WorkspaceTableChangeset { pub fn new(params: UpdateWorkspaceParams) -> Self { - WorkspaceChangeset { + WorkspaceTableChangeset { id: params.id, name: params.name, desc: params.desc, @@ -59,9 +57,9 @@ impl WorkspaceChangeset { } } -impl std::convert::Into for Workspace { - fn into(self) -> WorkspaceDetail { - WorkspaceDetail { +impl std::convert::Into for WorkspaceTable { + fn into(self) -> Workspace { + Workspace { id: self.id, name: self.name, desc: self.desc, diff --git a/rust-lib/flowy-workspace/tests/event/app_test.rs b/rust-lib/flowy-workspace/tests/event/app_test.rs index 8a00950875..90b2574376 100644 --- a/rust-lib/flowy-workspace/tests/event/app_test.rs +++ b/rust-lib/flowy-workspace/tests/event/app_test.rs @@ -1,15 +1,33 @@ -// #[test] -// fn app_create_success() { -// let request = CreateAppRequest { -// workspace_id: "".to_string(), -// name: "123".to_owned(), -// desc: "".to_owned(), -// color_style: Default::default(), -// }; -// -// let response = WorkspaceEventTester::new(CreateWorkspace) -// .request(request) -// .sync_send() -// .parse::(); -// dbg!(&response); -// } +use flowy_test::builder::WorkspaceTestBuilder; +use flowy_workspace::{ + entities::{ + app::{App, CreateAppRequest}, + workspace::UserWorkspaceDetail, + }, + event::WorkspaceEvent::{CreateApp, GetWorkspaceDetail}, +}; + +#[test] +fn app_create_success() { + let user_workspace = WorkspaceTestBuilder::new() + .event(GetWorkspaceDetail) + .sync_send() + .parse::(); + + let request = CreateAppRequest { + workspace_id: user_workspace.workspace.id, + name: "Github".to_owned(), + desc: "AppFlowy Github Project".to_owned(), + color_style: Default::default(), + }; + + let app_detail = WorkspaceTestBuilder::new() + .event(CreateApp) + .request(request) + .sync_send() + .parse::(); + + dbg!(&app_detail); +} + +// TODO 1) test update app 2) delete app diff --git a/rust-lib/flowy-workspace/tests/event/helper.rs b/rust-lib/flowy-workspace/tests/event/helper.rs index 58ad37b28d..9631890bfa 100644 --- a/rust-lib/flowy-workspace/tests/event/helper.rs +++ b/rust-lib/flowy-workspace/tests/event/helper.rs @@ -1,7 +1,4 @@ -use flowy_test::TestBuilder; -use flowy_workspace::errors::WorkspaceError; - -pub type WorkspaceTestBuilder = TestBuilder; +pub use flowy_test::builder::WorkspaceTestBuilder; pub(crate) fn invalid_workspace_name_test_case() -> Vec { vec!["", "1234".repeat(100).as_str()] diff --git a/rust-lib/flowy-workspace/tests/event/workspace_test.rs b/rust-lib/flowy-workspace/tests/event/workspace_test.rs index 8c00414098..8158ee9913 100644 --- a/rust-lib/flowy-workspace/tests/event/workspace_test.rs +++ b/rust-lib/flowy-workspace/tests/event/workspace_test.rs @@ -1,6 +1,6 @@ use crate::helper::*; use flowy_workspace::{ - entities::workspace::{CreateWorkspaceRequest, WorkspaceDetail}, + entities::workspace::{CreateWorkspaceRequest, UserWorkspaceDetail, Workspace}, event::WorkspaceEvent::*, prelude::*, }; @@ -16,10 +16,41 @@ fn workspace_create_success() { .event(CreateWorkspace) .request(request) .sync_send() - .parse::(); + .parse::(); dbg!(&response); } +#[test] +fn workspace_get_detail_success() { + let user_workspace = WorkspaceTestBuilder::new() + .event(GetWorkspaceDetail) + .sync_send() + .parse::(); + + dbg!(&user_workspace); +} + +#[test] +fn workspace_create_and_then_get_detail_success() { + let request = CreateWorkspaceRequest { + name: "Team A".to_owned(), + desc: "Team A Description".to_owned(), + }; + + let workspace = WorkspaceTestBuilder::new() + .event(CreateWorkspace) + .request(request) + .sync_send() + .parse::(); + + let user_workspace = WorkspaceTestBuilder::new() + .event(GetWorkspaceDetail) + .sync_send() + .parse::(); + + assert_eq!(workspace.name, user_workspace.workspace.name); +} + #[test] fn workspace_create_with_invalid_name_test() { for name in invalid_workspace_name_test_case() { @@ -40,21 +71,24 @@ fn workspace_create_with_invalid_name_test() { } } -// #[test] -// fn workspace_update_with_invalid_name_test() { -// for name in invalid_workspace_name_test_case() { -// let request = CreateWorkspaceRequest { -// name, -// desc: "".to_owned(), -// }; -// -// assert_eq!( -// WorkspaceEventTester::new(CreateWorkspace) -// .request(request) -// .sync_send() -// .error() -// .code, -// WorkspaceErrorCode::WorkspaceNameInvalid -// ) -// } -// } +#[test] +fn workspace_update_with_invalid_name_test() { + for name in invalid_workspace_name_test_case() { + let request = CreateWorkspaceRequest { + name, + desc: "".to_owned(), + }; + + assert_eq!( + WorkspaceTestBuilder::new() + .event(CreateWorkspace) + .request(request) + .sync_send() + .error() + .code, + WorkspaceErrorCode::WorkspaceNameInvalid + ) + } +} + +// TODO 1) delete workspace, but can't delete the last workspace diff --git a/scripts/flowy-tool/Cargo.toml b/scripts/flowy-tool/Cargo.toml index 25ce86882d..efef3f7a1b 100644 --- a/scripts/flowy-tool/Cargo.toml +++ b/scripts/flowy-tool/Cargo.toml @@ -22,4 +22,5 @@ phf = { version = "0.8.0", features = ["macros"] } similar = "1.2.2" dialoguer = "0.8.0" toml = "0.5.8" -serde = { version = "1.0", features = ["derive"] } \ No newline at end of file +serde = { version = "1.0", features = ["derive"] } +pathdiff = "0.2.0" \ No newline at end of file diff --git a/scripts/flowy-tool/src/proto/ast.rs b/scripts/flowy-tool/src/proto/ast.rs index bf780bb1d9..ab4722897f 100644 --- a/scripts/flowy-tool/src/proto/ast.rs +++ b/scripts/flowy-tool/src/proto/ast.rs @@ -78,6 +78,7 @@ fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec

, pub enums: Vec, @@ -121,6 +122,7 @@ impl FlutterProtobufInfo { model_dir } + #[allow(dead_code)] pub fn mod_file_path(&self) -> String { let mod_file_path = format!("{}/protobuf.dart", self.package_path); mod_file_path diff --git a/scripts/flowy-tool/src/util/file.rs b/scripts/flowy-tool/src/util/file.rs index 1719631560..b752866200 100644 --- a/scripts/flowy-tool/src/util/file.rs +++ b/scripts/flowy-tool/src/util/file.rs @@ -154,3 +154,14 @@ where path_and_name(path, name); } } + +#[allow(dead_code)] +pub fn suffix_relative_to_path(path: &str, base: &str) -> String { + let base = Path::new(base); + let path = Path::new(path); + path.strip_prefix(base) + .unwrap() + .to_str() + .unwrap() + .to_owned() +}