diff --git a/packages/share_plus/share_plus/example/lib/main.dart b/packages/share_plus/share_plus/example/lib/main.dart index 704e2cf95551546dade3e696b5f3f43e24b8eea4..41c939839ff80681365b4c866b7ff533ea7c21e7 100644 --- a/packages/share_plus/share_plus/example/lib/main.dart +++ b/packages/share_plus/share_plus/example/lib/main.dart @@ -63,9 +63,10 @@ class DemoAppState extends State { hintText: 'Enter some text and/or link to share', ), maxLines: null, - onChanged: (String value) => setState(() { - text = value; - }), + onChanged: (String value) => + setState(() { + text = value; + }), ), const SizedBox(height: 16), TextField( @@ -75,9 +76,10 @@ class DemoAppState extends State { hintText: 'Enter subject to share (optional)', ), maxLines: null, - onChanged: (String value) => setState(() { - subject = value; - }), + onChanged: (String value) => + setState(() { + subject = value; + }), ), const SizedBox(height: 16), TextField( @@ -112,7 +114,8 @@ class DemoAppState extends State { if (!kIsWeb && (Platform.isMacOS || Platform.isLinux || - Platform.isWindows)) { + Platform.isWindows || + defaultTargetPlatform == TargetPlatform.ohos)) { // Using `package:file_selector` on windows, macos & Linux, since `package:image_picker` is not supported. const XTypeGroup typeGroup = XTypeGroup( label: 'images', @@ -146,8 +149,14 @@ class DemoAppState extends State { builder: (BuildContext context) { return ElevatedButton( style: ElevatedButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.onPrimary, - backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: Theme + .of(context) + .colorScheme + .onPrimary, + backgroundColor: Theme + .of(context) + .colorScheme + .primary, ), onPressed: text.isEmpty && imagePaths.isEmpty ? null @@ -161,8 +170,14 @@ class DemoAppState extends State { builder: (BuildContext context) { return ElevatedButton( style: ElevatedButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.onPrimary, - backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: Theme + .of(context) + .colorScheme + .onPrimary, + backgroundColor: Theme + .of(context) + .colorScheme + .primary, ), onPressed: () { _onShareXFileFromAssets(context); @@ -176,8 +191,14 @@ class DemoAppState extends State { builder: (BuildContext context) { return ElevatedButton( style: ElevatedButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.onPrimary, - backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: Theme + .of(context) + .colorScheme + .onPrimary, + backgroundColor: Theme + .of(context) + .colorScheme + .primary, ), onPressed: fileName.isEmpty || text.isEmpty ? null diff --git a/packages/share_plus/share_plus/example/ohos/.gitignore b/packages/share_plus/share_plus/example/ohos/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f0364c33c52a9b8ce1b89ea309af9c8ea68f718d --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/.gitignore @@ -0,0 +1,16 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +entry/libs/arm64-v8a/libapp.so +entry/libs/arm64-v8a/libflutter.so +entry/libs/arm64-v8a/libvmservice_snapshot.so +entry/src/main/resources/rawfile/flutter_assets/ +har/flutter.har diff --git a/packages/share_plus/share_plus/example/ohos/AppScope/app.json5 b/packages/share_plus/share_plus/example/ohos/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c144b41ca675de084488b6371a76d8a4ade1760a --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "io.flutter.plugins.example", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/AppScope/resources/base/element/string.json b/packages/share_plus/share_plus/example/ohos/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..810f4a362c1d177309eec4f2efe5cac2f4558c28 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "example" + } + ] +} diff --git a/packages/share_plus/share_plus/example/ohos/AppScope/resources/base/media/app_icon.png b/packages/share_plus/share_plus/example/ohos/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/share_plus/share_plus/example/ohos/AppScope/resources/base/media/app_icon.png differ diff --git a/packages/share_plus/share_plus/example/ohos/build-profile.json5 b/packages/share_plus/share_plus/example/ohos/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6fb0c59b76d090432b5f2d463aad2c83deb4381c --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/build-profile.json5 @@ -0,0 +1,27 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} diff --git a/packages/share_plus/share_plus/example/ohos/dta/icudtl.dat b/packages/share_plus/share_plus/example/ohos/dta/icudtl.dat new file mode 100644 index 0000000000000000000000000000000000000000..d1f10917ab52e3ebd251abd7f5377d7196b80d67 Binary files /dev/null and b/packages/share_plus/share_plus/example/ohos/dta/icudtl.dat differ diff --git a/packages/share_plus/share_plus/example/ohos/entry/.gitignore b/packages/share_plus/share_plus/example/ohos/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2795a1c5b1fe53659dd1b71d90ba0592eaf7e043 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/.gitignore @@ -0,0 +1,7 @@ + +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/build-profile.json5 b/packages/share_plus/share_plus/example/ohos/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..633d360fbc91a3186a23b66ab71b27e5618944cb --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/build-profile.json5 @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "apiType": 'stageMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + "runtimeOS": "HarmonyOS" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/hvigorfile.ts b/packages/share_plus/share_plus/example/ohos/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..894fc15c6b793f085e6c8506e43d719af658e8ff --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/hvigorfile.ts @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { hapTasks } from '@ohos/hvigor-ohos-plugin'; diff --git a/packages/share_plus/share_plus/example/ohos/entry/oh-package.json5 b/packages/share_plus/share_plus/example/ohos/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..33beed57bd0c26a67f2bdcf04a4809732e6f179c --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + } +} diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets b/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..a00049282e93c69f1b3dcd987538024f47e40ace --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { FlutterAbility } from '@ohos/flutter_ohos' +import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant'; +import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine'; + +export default class EntryAbility extends FlutterAbility { + configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + GeneratedPluginRegistrant.registerWith(flutterEngine) + } +} diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/pages/Index.ets b/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..1125f9fdd95f4310a182c1c9e3680f37f73686c9 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import common from '@ohos.app.ability.common'; +import { FlutterPage } from '@ohos/flutter_ohos' + +let storage = LocalStorage.getShared() +const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS' + +@Entry(storage) +@Component +struct Index { + private context = getContext(this) as common.UIAbilityContext + @LocalStorageLink('viewId') viewId: string = ""; + + build() { + Column() { + FlutterPage({ viewId: this.viewId }) + } + } + + onBackPress(): boolean { + this.context.eventHub.emit(EVENT_BACK_PRESS) + return true + } +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets b/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets new file mode 100644 index 0000000000000000000000000000000000000000..8d0d770fd4be5bfd5a9f661e4caf1fdebf53ca36 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/ets/plugins/GeneratedPluginRegistrant.ets @@ -0,0 +1,34 @@ +import { FlutterEngine, Log } from '@ohos/flutter_ohos'; +import FileSelectorOhosPlugin from 'file_selector_ohos'; +import ImagePickerPlugin from 'image_picker_ohos'; +import IntegrationTestPlugin from 'integration_test'; +import PathProviderPlugin from 'path_provider_ohos'; +import SharePlusOhosPlugin from 'share_plus'; + +/** + * Generated file. Do not edit. + * This file is generated by the Flutter tool based on the + * plugins that support the Ohos platform. + */ + +const TAG = "GeneratedPluginRegistrant"; + +export class GeneratedPluginRegistrant { + + static registerWith(flutterEngine: FlutterEngine) { + try { + flutterEngine.getPlugins()?.add(new FileSelectorOhosPlugin()); + flutterEngine.getPlugins()?.add(new ImagePickerPlugin()); + flutterEngine.getPlugins()?.add(new IntegrationTestPlugin()); + flutterEngine.getPlugins()?.add(new PathProviderPlugin()); + flutterEngine.getPlugins()?.add(new SharePlusOhosPlugin()); + } catch (e) { + Log.e( + TAG, + "Tried to register plugins with FlutterEngine (" + + flutterEngine + + ") failed."); + Log.e(TAG, "Received exception while registering", e); + } + } +} diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/module.json5 b/packages/share_plus/share_plus/example/ohos/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7bbf78b18f39991b1404061c7437538c7d532bb7 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/module.json5 @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + {"name" : "ohos.permission.INTERNET"}, + ] + } +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/element/color.json b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/element/string.json b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..67e0f4ff4ac762d1714f6e215c6636a4ad3d620e --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "example" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/media/icon.png b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/media/icon.png differ diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/profile/main_pages.json b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/en_US/element/string.json b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..67e0f4ff4ac762d1714f6e215c6636a4ad3d620e --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "example" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/zh_CN/element/string.json b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..601e2b5a1c273aa04920b126e3ab715a4450e58f --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "example" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..25d4c71ff3cd584f5d64f6f8c0ac864928c234c4 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function abilityTest() { + describe('ActsAbilityTest', function () { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(function () { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(function () { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(function () { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(function () { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain',0, function () { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc' + let b = 'b' + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b) + expect(a).assertEqual(a) + }) + }) +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/test/List.test.ets b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f4140030e65d20df6af30a6bf51e464dea8f8aa6 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import abilityTest from './Ability.test' + +export default function testsuite() { + abilityTest() +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ca645e6013cfce8e7dbb728313cb8840c4da660 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; + +export default class TestAbility extends UIAbility { + onCreate(want, launchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? ''); + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..cef0447cd2f137ef82d223ead2e156808878ab90 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..1def08f2e9dcbfa3454a07b7a3b82b173bb90d02 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/module.json5 b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fab77ce2e0c61e3ad010bab5b27ccbd15f9a8c96 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/module.json5 @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/element/color.json b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/element/string.json b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..65d8fa5a7cf54aa3943dcd0214f58d1771bc1f6c --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/media/icon.png b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/packages/share_plus/share_plus/example/ohos/hvigor/hvigor-config.json5 b/packages/share_plus/share_plus/example/ohos/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..898c353ada0cf4f01739ead437b3180cda8b54c8 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/hvigor/hvigor-config.json5 @@ -0,0 +1,8 @@ +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "properties": { + "ohos.nativeResolver": false + } +} diff --git a/packages/share_plus/share_plus/example/ohos/hvigorfile.ts b/packages/share_plus/share_plus/example/ohos/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..8f2d2aafe6d6a3a71a9944ebd0c91fbc308ac9d1 --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/hvigorfile.ts @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/example/ohos/oh-package.json5 b/packages/share_plus/share_plus/example/ohos/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..cd36c484e1fedaf2af803ba874644fb6b430231e --- /dev/null +++ b/packages/share_plus/share_plus/example/ohos/oh-package.json5 @@ -0,0 +1,18 @@ +{ + "modelVersion": "5.0.0", + "name": "apptemplate", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "@ohos/flutter_ohos": "file:./har/flutter.har" + }, + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, + "overrides": { + "@ohos/flutter_ohos": "file:./har/flutter.har", + } +} diff --git a/packages/share_plus/share_plus/example/pubspec.yaml b/packages/share_plus/share_plus/example/pubspec.yaml index 62e013bbbb978abe586324bdc8832d7132665fea..0572ab593614c6d6471013462f8cbd84064c44e6 100644 --- a/packages/share_plus/share_plus/example/pubspec.yaml +++ b/packages/share_plus/share_plus/example/pubspec.yaml @@ -4,9 +4,40 @@ description: Demonstrates how to use the share_plus plugin. dependencies: flutter: sdk: flutter - share_plus: ^10.1.1 - image_picker: ^1.1.2 - file_selector: ^1.0.3 + share_plus: + path: ../ + image_picker: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + ref: master + path: packages/image_picker/image_picker + file_selector: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + ref: master + path: packages/file_selector/file_selector + path_provider: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + ref: master + path: packages/path_provider/path_provider + +dependency_overrides: + image_picker_ohos: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + ref: br_optimize_har_structure + path: packages/image_picker/image_picker_ohos + file_selector_ohos: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + ref: br_optimize_har_structure + path: packages/file_selector/file_selector_ohos + path_provider_ohos: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + ref: br_optimize_har_structure + path: packages/path_provider/path_provider_ohos dev_dependencies: flutter_driver: @@ -15,7 +46,7 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter - flutter_lints: ^5.0.0 + flutter_lints: ^2.0.1 flutter: uses-material-design: true diff --git a/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m b/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m index bb3d501e501d5da5653b3304d08fa4b28945d048..058f9ec209c40cb3683a34eb9f0cf49ebebee446 100644 --- a/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m +++ b/packages/share_plus/share_plus/ios/share_plus/Sources/share_plus/FPPSharePlusPlugin.m @@ -8,35 +8,37 @@ static NSString *const PLATFORM_CHANNEL = @"dev.fluttercommunity.plus/share"; static UIViewController *RootViewController() { - if (@available(iOS 13, *)) { // UIApplication.keyWindow is deprecated - NSSet *scenes = [[UIApplication sharedApplication] connectedScenes]; - for (UIScene *scene in scenes) { - if ([scene isKindOfClass:[UIWindowScene class]]) { - NSArray *windows = ((UIWindowScene *)scene).windows; - for (UIWindow *window in windows) { - if (window.isKeyWindow) { - return window.rootViewController; - } + if (@available + (iOS + 13, *)) { // UIApplication.keyWindow is deprecated + NSSet *scenes = [[UIApplication sharedApplication] connectedScenes]; + for (UIScene *scene in scenes) { + if ([scene isKindOfClass:[UIWindowScene class]]) { + NSArray *windows = ((UIWindowScene *) scene).windows; + for (UIWindow *window in windows) { + if (window.isKeyWindow) { + return window.rootViewController; + } + } + } } - } + return nil; + } else { + return [UIApplication sharedApplication].keyWindow.rootViewController; } - return nil; - } else { - return [UIApplication sharedApplication].keyWindow.rootViewController; - } } static UIViewController * TopViewControllerForViewController(UIViewController *viewController) { - if (viewController.presentedViewController) { - return TopViewControllerForViewController( - viewController.presentedViewController); - } - if ([viewController isKindOfClass:[UINavigationController class]]) { - return TopViewControllerForViewController( - ((UINavigationController *)viewController).visibleViewController); - } - return viewController; + if (viewController.presentedViewController) { + return TopViewControllerForViewController( + viewController.presentedViewController); + } + if ([viewController isKindOfClass:[UINavigationController class]]) { + return TopViewControllerForViewController( + ((UINavigationController *) viewController).visibleViewController); + } + return viewController; } // We need the companion to avoid ARC deadlock @@ -53,21 +55,21 @@ TopViewControllerForViewController(UIViewController *viewController) { @implementation UIActivityViewSuccessCompanion - (id)initWithResult:(FlutterResult)result { - if (self = [super init]) { - self.result = result; - self.completed = false; - } - return self; + if (self = [super init]) { + self.result = result; + self.completed = false; + } + return self; } // We use dealloc as the share-sheet might disappear (e.g. iCloud photo album // creation) and could then reappear if the user cancels - (void)dealloc { - if (self.completed) { - self.result(self.activityType); - } else { - self.result(@""); - } + if (self.completed) { + self.result(self.activityType); + } else { + self.result(@""); + } } @end @@ -99,343 +101,345 @@ TopViewControllerForViewController(UIViewController *viewController) { subject:(NSString *)subject NS_DESIGNATED_INITIALIZER; - (instancetype)init - __attribute__((unavailable("Use initWithSubject:text: instead"))); +__attribute__((unavailable("Use initWithSubject:text: instead"))); @end @implementation SharePlusData - (instancetype)init { - [super doesNotRecognizeSelector:_cmd]; - return nil; + [super doesNotRecognizeSelector:_cmd]; + return nil; } - (instancetype)initWithSubject:(NSString *)subject text:(NSString *)text { - self = [super init]; - if (self) { - _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; - _text = text; - } - return self; + self = [super init]; + if (self) { + _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; + _text = text; + } + return self; } - (instancetype)initWithFile:(NSString *)path mimeType:(NSString *)mimeType { - self = [super init]; - if (self) { - _path = path; - _mimeType = mimeType; - } - return self; + self = [super init]; + if (self) { + _path = path; + _mimeType = mimeType; + } + return self; } - (instancetype)initWithFile:(NSString *)path mimeType:(NSString *)mimeType subject:(NSString *)subject { - self = [super init]; - if (self) { - _path = path; - _mimeType = mimeType; - _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; - } - return self; + self = [super init]; + if (self) { + _path = path; + _mimeType = mimeType; + _subject = [subject isKindOfClass:NSNull.class] ? @"" : subject; + } + return self; } - (id)activityViewControllerPlaceholderItem: - (UIActivityViewController *)activityViewController { - return [self - activityViewController:activityViewController - itemForActivityType:@"dev.fluttercommunity.share_plus.placeholder"]; + (UIActivityViewController *)activityViewController { + return [self + activityViewController:activityViewController + itemForActivityType:@"dev.fluttercommunity.share_plus.placeholder"]; } - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(UIActivityType)activityType { - if (!_path || !_mimeType) { - return _text; - } - - // If the shared file is an image return an UIImage for the placeholder - // to show a preview. - if ([activityType - isEqualToString:@"dev.fluttercommunity.share_plus.placeholder"] && - [_mimeType hasPrefix:@"image/"]) { - UIImage *image = [UIImage imageWithContentsOfFile:_path]; - return image; - } + if (!_path || !_mimeType) { + return _text; + } - // Return an NSURL for the real share to conserve the file name - NSURL *url = [NSURL fileURLWithPath:_path]; - return url; + // If the shared file is an image return an UIImage for the placeholder + // to show a preview. + if ([activityType + isEqualToString:@"dev.fluttercommunity.share_plus.placeholder"] && + [_mimeType hasPrefix:@"image/"]) { + UIImage *image = [UIImage imageWithContentsOfFile:_path]; + return image; + } + + // Return an NSURL for the real share to conserve the file name + NSURL *url = [NSURL fileURLWithPath:_path]; + return url; } - (NSString *)activityViewController: - (UIActivityViewController *)activityViewController + (UIActivityViewController *)activityViewController subjectForActivityType:(UIActivityType)activityType { - return _subject; + return _subject; } - (UIImage *)activityViewController: - (UIActivityViewController *)activityViewController + (UIActivityViewController *)activityViewController thumbnailImageForActivityType:(UIActivityType)activityType suggestedSize:(CGSize)suggestedSize { - if (!_path || !_mimeType || ![_mimeType hasPrefix:@"image/"]) { - return nil; - } + if (!_path || !_mimeType || ![_mimeType hasPrefix:@"image/"]) { + return nil; + } - UIImage *image = [UIImage imageWithContentsOfFile:_path]; - return [self imageWithImage:image scaledToSize:suggestedSize]; + UIImage *image = [UIImage imageWithContentsOfFile:_path]; + return [self imageWithImage:image scaledToSize:suggestedSize]; } - (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize { - UIGraphicsBeginImageContext(newSize); - [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return newImage; + UIGraphicsBeginImageContext(newSize); + [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; } - (LPLinkMetadata *)activityViewControllerLinkMetadata: - (UIActivityViewController *)activityViewController - API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0)) { - LPLinkMetadata *metadata = [[LPLinkMetadata alloc] init]; - - if ([_subject length] > 0) { - metadata.title = _subject; - } else if ([_text length] > 0) { - metadata.title = _text; - } - - if (_path) { - NSString *extesnion = [_path pathExtension]; - - unsigned long long rawSize = ( - [[[NSFileManager defaultManager] attributesOfItemAtPath:_path - error:nil] fileSize]); - NSString *readableSize = [NSByteCountFormatter - stringFromByteCount:rawSize - countStyle:NSByteCountFormatterCountStyleFile]; - - NSString *description = @""; - - if (![extesnion isEqualToString:@""]) { - description = - [description stringByAppendingString:[extesnion uppercaseString]]; - description = [description stringByAppendingString:@" • "]; - description = [description stringByAppendingString:readableSize]; - } else { - description = [description stringByAppendingString:readableSize]; + (UIActivityViewController *)activityViewController +API_AVAILABLE + +(macos(10.15), ios(13.0), watchos(6.0)) { + LPLinkMetadata *metadata = [[LPLinkMetadata alloc] init]; + + if ([_subject length] > 0) { + metadata.title = _subject; + } else if ([_text length] > 0) { + metadata.title = _text; } - // https://stackoverflow.com/questions/60563773/ios-13-share-sheet-changing-subtitle-item-description - metadata.originalURL = [NSURL fileURLWithPath:description]; - if (_mimeType && [_mimeType hasPrefix:@"image/"]) { - UIImage *image = [UIImage imageWithContentsOfFile:_path]; - metadata.imageProvider = [[NSItemProvider alloc] - initWithObject:[self imageWithImage:image - scaledToSize:CGSizeMake(120, 120)]]; + if (_path) { + NSString *extesnion = [_path pathExtension]; + + unsigned long long rawSize = ( + [[[NSFileManager defaultManager] attributesOfItemAtPath:_path + error:nil] fileSize]); + NSString *readableSize = [NSByteCountFormatter + stringFromByteCount:rawSize + countStyle:NSByteCountFormatterCountStyleFile]; + + NSString *description = @""; + + if (![extesnion isEqualToString:@""]) { + description = + [description stringByAppendingString:[extesnion uppercaseString]]; + description = [description stringByAppendingString:@" • "]; + description = [description stringByAppendingString:readableSize]; + } else { + description = [description stringByAppendingString:readableSize]; + } + + // https://stackoverflow.com/questions/60563773/ios-13-share-sheet-changing-subtitle-item-description + metadata.originalURL = [NSURL fileURLWithPath:description]; + if (_mimeType && [_mimeType hasPrefix:@"image/"]) { + UIImage *image = [UIImage imageWithContentsOfFile:_path]; + metadata.imageProvider = [[NSItemProvider alloc] + initWithObject:[self imageWithImage:image + scaledToSize:CGSizeMake(120, 120)]]; + } } - } - return metadata; + return metadata; } @end @implementation FPPSharePlusPlugin -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *shareChannel = - [FlutterMethodChannel methodChannelWithName:PLATFORM_CHANNEL - binaryMessenger:registrar.messenger]; - - [shareChannel - setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { - NSDictionary *arguments = [call arguments]; - NSNumber *originX = arguments[@"originX"]; - NSNumber *originY = arguments[@"originY"]; - NSNumber *originWidth = arguments[@"originWidth"]; - NSNumber *originHeight = arguments[@"originHeight"]; - - CGRect originRect = CGRectZero; - if (originX && originY && originWidth && originHeight) { - originRect = - CGRectMake([originX doubleValue], [originY doubleValue], - [originWidth doubleValue], [originHeight doubleValue]); - } - - if ([@"share" isEqualToString:call.method]) { - NSString *shareText = arguments[@"text"]; - NSString *shareSubject = arguments[@"subject"]; - - if (shareText.length == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Non-empty text expected" - details:nil]); - return; - } - - UIViewController *rootViewController = RootViewController(); - if (!rootViewController) { - result([FlutterError errorWithCode:@"error" - message:@"No root view controller found" - details:nil]); - return; - } - UIViewController *topViewController = - TopViewControllerForViewController(rootViewController); - - [self shareText:shareText - subject:shareSubject - withController:topViewController - atSource:originRect - toResult:result]; - } else if ([@"shareFiles" isEqualToString:call.method]) { - NSArray *paths = arguments[@"paths"]; - NSArray *mimeTypes = arguments[@"mimeTypes"]; - NSString *subject = arguments[@"subject"]; - NSString *text = arguments[@"text"]; - - if (paths.count == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Non-empty paths expected" - details:nil]); - return; - } - - for (NSString *path in paths) { - if (path.length == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Each path must not be empty" - details:nil]); - return; - } - } - - UIViewController *rootViewController = RootViewController(); - if (!rootViewController) { - result([FlutterError errorWithCode:@"error" - message:@"No root view controller found" - details:nil]); - return; - } - UIViewController *topViewController = - TopViewControllerForViewController(rootViewController); - [self shareFiles:paths - withMimeType:mimeTypes - withSubject:subject - withText:text - withController:topViewController - atSource:originRect - toResult:result]; - } else if ([@"shareUri" isEqualToString:call.method]) { - NSString *uri = arguments[@"uri"]; - - if (uri.length == 0) { - result([FlutterError errorWithCode:@"error" - message:@"Non-empty uri expected" - details:nil]); - return; - } - - UIViewController *rootViewController = RootViewController(); - if (!rootViewController) { - result([FlutterError errorWithCode:@"error" - message:@"No root view controller found" - details:nil]); - return; - } - UIViewController *topViewController = - TopViewControllerForViewController(rootViewController); - - [self shareUri:uri - withController:topViewController - atSource:originRect - toResult:result]; - } else { - result(FlutterMethodNotImplemented); - } - }]; ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *shareChannel = + [FlutterMethodChannel methodChannelWithName:PLATFORM_CHANNEL + binaryMessenger:registrar.messenger]; + + [shareChannel + setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) { + NSDictionary *arguments = [call arguments]; + NSNumber *originX = arguments[@"originX"]; + NSNumber *originY = arguments[@"originY"]; + NSNumber *originWidth = arguments[@"originWidth"]; + NSNumber *originHeight = arguments[@"originHeight"]; + + CGRect originRect = CGRectZero; + if (originX && originY && originWidth && originHeight) { + originRect = + CGRectMake([originX doubleValue], [originY doubleValue], + [originWidth doubleValue], [originHeight doubleValue]); + } + + if ([@"share" isEqualToString:call.method]) { + NSString *shareText = arguments[@"text"]; + NSString *shareSubject = arguments[@"subject"]; + + if (shareText.length == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Non-empty text expected" + details:nil]); + return; + } + + UIViewController *rootViewController = RootViewController(); + if (!rootViewController) { + result([FlutterError errorWithCode:@"error" + message:@"No root view controller found" + details:nil]); + return; + } + UIViewController *topViewController = + TopViewControllerForViewController(rootViewController); + + [self shareText:shareText + subject:shareSubject + withController:topViewController + atSource:originRect + toResult:result]; + } else if ([@"shareFiles" isEqualToString:call.method]) { + NSArray *paths = arguments[@"paths"]; + NSArray *mimeTypes = arguments[@"mimeTypes"]; + NSString *subject = arguments[@"subject"]; + NSString *text = arguments[@"text"]; + + if (paths.count == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Non-empty paths expected" + details:nil]); + return; + } + + for (NSString *path in paths) { + if (path.length == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Each path must not be empty" + details:nil]); + return; + } + } + + UIViewController *rootViewController = RootViewController(); + if (!rootViewController) { + result([FlutterError errorWithCode:@"error" + message:@"No root view controller found" + details:nil]); + return; + } + UIViewController *topViewController = + TopViewControllerForViewController(rootViewController); + [self shareFiles:paths + withMimeType:mimeTypes + withSubject:subject + withText:text + withController:topViewController + atSource:originRect + toResult:result]; + } else if ([@"shareUri" isEqualToString:call.method]) { + NSString *uri = arguments[@"uri"]; + + if (uri.length == 0) { + result([FlutterError errorWithCode:@"error" + message:@"Non-empty uri expected" + details:nil]); + return; + } + + UIViewController *rootViewController = RootViewController(); + if (!rootViewController) { + result([FlutterError errorWithCode:@"error" + message:@"No root view controller found" + details:nil]); + return; + } + UIViewController *topViewController = + TopViewControllerForViewController(rootViewController); + + [self shareUri:uri + withController:topViewController + atSource:originRect + toResult:result]; + } else { + result(FlutterMethodNotImplemented); + } + }]; } -+ (void)share:(NSArray *)shareItems - withSubject:(NSString *)subject - withController:(UIViewController *)controller - atSource:(CGRect)origin - toResult:(FlutterResult)result { - UIActivityViewSuccessController *activityViewController = - [[UIActivityViewSuccessController alloc] initWithActivityItems:shareItems - applicationActivities:nil]; - - // Force subject when sharing a raw url or files - if (![subject isKindOfClass:[NSNull class]]) { - [activityViewController setValue:subject forKey:@"subject"]; - } - - activityViewController.popoverPresentationController.sourceView = - controller.view; - BOOL isCoordinateSpaceOfSourceView = - CGRectContainsRect(controller.view.frame, origin); - - // If device is e.g. an iPad then hasPopoverPresentationController is true - BOOL hasPopoverPresentationController = - [activityViewController popoverPresentationController] != NULL; - if (hasPopoverPresentationController && - (!isCoordinateSpaceOfSourceView || CGRectIsEmpty(origin))) { - NSString *sharePositionIssue = [NSString - stringWithFormat: - @"sharePositionOrigin: argument must be set, %@ must be non-zero " - @"and within coordinate space of source view: %@", - NSStringFromCGRect(origin), - NSStringFromCGRect(controller.view.bounds)]; - - result([FlutterError errorWithCode:@"error" - message:sharePositionIssue - details:nil]); - return; - } - - if (!CGRectIsEmpty(origin)) { - activityViewController.popoverPresentationController.sourceRect = origin; - } - - UIActivityViewSuccessCompanion *companion = - [[UIActivityViewSuccessCompanion alloc] initWithResult:result]; - activityViewController.companion = companion; - activityViewController.completionWithItemsHandler = - ^(UIActivityType activityType, BOOL completed, NSArray *returnedItems, - NSError *activityError) { - companion.activityType = activityType; - companion.completed = completed; - }; - - [controller presentViewController:activityViewController - animated:YES - completion:nil]; ++ (void) share:(NSArray *)shareItems + withSubject:(NSString *)subject +withController:(UIViewController *)controller + atSource:(CGRect)origin + toResult:(FlutterResult)result { + UIActivityViewSuccessController *activityViewController = + [[UIActivityViewSuccessController alloc] initWithActivityItems:shareItems + applicationActivities:nil]; + + // Force subject when sharing a raw url or files + if (![subject isKindOfClass:[NSNull class]]) { + [activityViewController setValue:subject forKey:@"subject"]; + } + + activityViewController.popoverPresentationController.sourceView = + controller.view; + BOOL isCoordinateSpaceOfSourceView = + CGRectContainsRect(controller.view.frame, origin); + + // If device is e.g. an iPad then hasPopoverPresentationController is true + BOOL hasPopoverPresentationController = + [activityViewController popoverPresentationController] != NULL; + if (hasPopoverPresentationController && + (!isCoordinateSpaceOfSourceView || CGRectIsEmpty(origin))) { + NSString *sharePositionIssue = [NSString + stringWithFormat: + @"sharePositionOrigin: argument must be set, %@ must be non-zero " + @"and within coordinate space of source view: %@", + NSStringFromCGRect(origin), + NSStringFromCGRect(controller.view.bounds)]; + + result([FlutterError errorWithCode:@"error" + message:sharePositionIssue + details:nil]); + return; + } + + if (!CGRectIsEmpty(origin)) { + activityViewController.popoverPresentationController.sourceRect = origin; + } + + UIActivityViewSuccessCompanion *companion = + [[UIActivityViewSuccessCompanion alloc] initWithResult:result]; + activityViewController.companion = companion; + activityViewController.completionWithItemsHandler = + ^(UIActivityType activityType, BOOL completed, NSArray *returnedItems, + NSError *activityError) { + companion.activityType = activityType; + companion.completed = completed; + }; + + [controller presentViewController:activityViewController + animated:YES + completion:nil]; } + (void)shareUri:(NSString *)uri - withController:(UIViewController *)controller - atSource:(CGRect)origin - toResult:(FlutterResult)result { - NSURL *data = [NSURL URLWithString:uri]; - [self share:@[ data ] - withSubject:nil - withController:controller - atSource:origin - toResult:result]; + withController:(UIViewController *)controller + atSource:(CGRect)origin + toResult:(FlutterResult)result { + NSURL *data = [NSURL URLWithString:uri]; + [self share:@[data] + withSubject:nil + withController:controller + atSource:origin + toResult:result]; } + (void)shareText:(NSString *)shareText - subject:(NSString *)subject - withController:(UIViewController *)controller - atSource:(CGRect)origin - toResult:(FlutterResult)result { - NSObject *data = [[SharePlusData alloc] initWithSubject:subject - text:shareText]; - [self share:@[ data ] - withSubject:subject - withController:controller - atSource:origin - toResult:result]; + subject:(NSString *)subject + withController:(UIViewController *)controller + atSource:(CGRect)origin + toResult:(FlutterResult)result { + NSObject *data = [[SharePlusData alloc] initWithSubject:subject + text:shareText]; + [self share:@[data] + withSubject:subject + withController:controller + atSource:origin + toResult:result]; } + (void)shareFiles:(NSArray *)paths @@ -445,25 +449,25 @@ TopViewControllerForViewController(UIViewController *viewController) { withController:(UIViewController *)controller atSource:(CGRect)origin toResult:(FlutterResult)result { - NSMutableArray *items = [[NSMutableArray alloc] init]; - - for (int i = 0; i < [paths count]; i++) { - NSString *path = paths[i]; - NSString *mimeType = mimeTypes[i]; - [items addObject:[[SharePlusData alloc] initWithFile:path - mimeType:mimeType - subject:subject]]; - } - if (text != nil) { - NSObject *data = [[SharePlusData alloc] initWithSubject:subject text:text]; - [items addObject:data]; - } - - [self share:items - withSubject:subject - withController:controller - atSource:origin - toResult:result]; + NSMutableArray *items = [[NSMutableArray alloc] init]; + + for (int i = 0; i < [paths count]; i++) { + NSString *path = paths[i]; + NSString *mimeType = mimeTypes[i]; + [items addObject:[[SharePlusData alloc] initWithFile:path + mimeType:mimeType + subject:subject]]; + } + if (text != nil) { + NSObject *data = [[SharePlusData alloc] initWithSubject:subject text:text]; + [items addObject:data]; + } + + [self share:items + withSubject:subject + withController:controller + atSource:origin + toResult:result]; } @end diff --git a/packages/share_plus/share_plus/ohos/.gitignore b/packages/share_plus/share_plus/ohos/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6f7b4f89c49a6abadc383d9665d3b4c171d466bc --- /dev/null +++ b/packages/share_plus/share_plus/ohos/.gitignore @@ -0,0 +1,17 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test + +/entry/libs/arm64-v8a/libflutter.so +/entry/src/main/resources/rawfile/flutter_assets +**.har +**/oh-package-lock.json5 +BuildProfile.ets diff --git a/packages/share_plus/share_plus/ohos/build-profile.json5 b/packages/share_plus/share_plus/ohos/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8f398ca7b6352455fa236ecd424c5cbfa7495382 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/build-profile.json5 @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "apiType": 'stageMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + "runtimeOS": "HarmonyOS" + } + ] +} diff --git a/packages/share_plus/share_plus/ohos/hvigorfile.ts b/packages/share_plus/share_plus/ohos/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..5384423c6ef108fd39dd8d7d2cd0489769f720a3 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/hvigorfile.ts @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { harTasks } from '@ohos/hvigor-ohos-plugin'; diff --git a/packages/share_plus/share_plus/ohos/index.ets b/packages/share_plus/share_plus/ohos/index.ets new file mode 100644 index 0000000000000000000000000000000000000000..b6a931e09943be8fcbcecdd1450395bd3264387e --- /dev/null +++ b/packages/share_plus/share_plus/ohos/index.ets @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import SharePlusOhosPlugin from './src/main/ets/dev/fluttercommunity/plus/share/SharePlusOhosPlugin'; +export default SharePlusOhosPlugin; diff --git a/packages/share_plus/share_plus/ohos/oh-package.json5 b/packages/share_plus/share_plus/ohos/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5fa924d5eefa90b0a87b97da089ef0a805c2665b --- /dev/null +++ b/packages/share_plus/share_plus/ohos/oh-package.json5 @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "name": "share_plus", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": { + "@ohos/flutter_ohos": "file:./har/flutter.har" + } +} diff --git a/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/MethodChannelHandlerImpl.ets b/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/MethodChannelHandlerImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..a030c5d1f7c488450f570b374a1b995bd55bb5f4 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/MethodChannelHandlerImpl.ets @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import { MethodCall } from '@ohos/flutter_ohos'; +import { MethodCallHandler, MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import Share from './Share'; + +const TAG = 'MethodCallHandlerImpl'; + +export default class MethodCallHandlerImpl implements MethodCallHandler { + private share: Share | null = null; + + constructor(share: Share) { + this.share = share; + } + + onMethodCall(call: MethodCall, result: MethodResult): void { + Log.i(TAG, "onMethodCall step in"); + let method: string = call.method; + Log.i(TAG, "Received '" + method + "' message."); + const isWithResult: boolean = true; + try { + switch (method) { + case 'shareUri': + this.share?.share(call.argument('uri') as string, null, false, result); + if (!isWithResult) { + result.success(null); + } + break; + case 'share': + this.share?.share( + call.argument('text') as string, + call.argument('subject') as string, + isWithResult, + result, + ); + if (!isWithResult) { + result.success("dev.fluttercommunity.plus/share/unavailable"); + } + break; + case 'shareFiles': + this.share?.shareFiles( + call.argument('paths'), + call.argument('mimeTypes'), + call.argument('text'), + call.argument('subject'), + call.argument('fileNameOverrides'), + isWithResult, + result); + if (!isWithResult) { + result.success("dev.fluttercommunity.plus/share/unavailable"); + } + break; + default: + result.notImplemented(); + break; + } + } catch (err) { + Log.e(TAG, 'err:' + JSON.stringify(err)); + } + } +} diff --git a/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/Share.ets b/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/Share.ets new file mode 100644 index 0000000000000000000000000000000000000000..02748e3f6f5bb88cbc4782e615b59dfcfb044fb1 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/Share.ets @@ -0,0 +1,191 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import common from '@ohos.app.ability.common'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import List from '@ohos.util.List'; +import fs from '@ohos.file.fs'; +import { fileUri } from '@kit.CoreFileKit'; +import { MethodResult } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import systemShare from '@hms.collaboration.systemShare'; +import uniformTypeDescriptor from '@ohos.data.uniformTypeDescriptor'; + +const TAG = 'Share'; + +export default class Share { + public context: common.Context | null = null; + public ability?: UIAbility | null = null; + + constructor(context: common.Context, ability?: UIAbility) { + this.context = context; + } + + public setAbility(ability: UIAbility | null): void { + this.ability = ability; + } + + public async share(text: string, subject: string | null, withResult: boolean, result: MethodResult,): Promise { + Log.i(TAG, "share"); + let record: systemShare.SharedRecord = { + utd: uniformTypeDescriptor.getUniformDataTypeByMIMEType('text/plain'), + content: text, + title: subject! + } + let data = new systemShare.SharedData(record); + this.startShare(data, withResult, result); + } + + public async shareFiles(paths: List, mimeTypes: List | null, text: string, subject: string | null, + fileNameOverrides: string | null, withResult: boolean, result: MethodResult): Promise { + Log.i(TAG, "shareFiles"); + this.clearShareCacheFolder() + let fileUris = await this.getUrisForPaths(paths) + try { + let data: systemShare.SharedData | null = null; + if (fileUris.length == 0 && text.length !== 0) { + this.share(text, subject, withResult, result) + return + } else if (fileUris.length == 1) { + let record: systemShare.SharedRecord = { + utd: this.getUniformTypeDescriptor(fileUris![0]), + uri: fileUris[0], + content: text, + title: fileNameOverrides?.toString(), + } + data = new systemShare.SharedData(record); + } else { + if (text) { + let record: systemShare.SharedRecord = { + utd: uniformTypeDescriptor.getUniformDataTypeByMIMEType('text/plain'), + content: text, + title: subject! + } + data = new systemShare.SharedData(record); + } + fileUris.forEach((uri: string, index: number) => { + let record: systemShare.SharedRecord = { + utd: this.getUniformTypeDescriptor(uri), + uri: uri, + } + if (data) { + data.addRecord(record); + } else { + data = new systemShare.SharedData(record); + } + }) + } + this.startShare(data!, withResult, result); + } catch (err) { + Log.e(TAG, 'err:' + JSON.stringify(err)); + } + } + + private startShare(data: systemShare.SharedData, withResult: boolean, result: MethodResult): void { + Log.i(TAG, "startShare"); + try { + let controller = new systemShare.ShareController(data); + if (withResult) { + controller.on('dismiss', () => { + result.success(''); + }); + withResult = false; + } + controller.show(this.ability?.context, { + previewMode: systemShare.SharePreviewMode.DETAIL, + selectionMode: systemShare.SelectionMode.BATCH + }); + withResult = true; + } catch (err) { + Log.e(TAG, 'err:' + JSON.stringify(err)); + } + } + + private getUniformTypeDescriptor(fileUri: string): string { + const dotIndex = fileUri.lastIndexOf('.'); + if (dotIndex != -1) { + const fileExtension = '.' + fileUri.substring(dotIndex + 1); + return uniformTypeDescriptor.getUniformDataTypeByFilenameExtension(fileExtension) ?? 'general.file'; + } + return 'general.file'; + } + + private shareCacheFolder(): string { + Log.i(TAG, "shareCacheFolder"); + return this.context?.cacheDir + '/share_plus'; + } + + private async getUrisForPaths(paths: List): Promise> { + Log.i(TAG, "getUrisForPaths"); + let uris = new Array(); + try { + paths.forEach(async path => { + let file: string; + if (this.fileIsInShareCache(path)) { + throw new Error(`Shared file can not be located in '${this.shareCacheFolder()}`); + } + file = await this.copyToShareCacheFolder(path); + uris.push(fileUri.getUriFromPath(file)); + }) + } catch (err) { + Log.e(TAG, 'err:' + JSON.stringify(err)); + } + return uris + } + + private fileIsInShareCache(file: string): boolean { + Log.i(TAG, "fileIsInShareCache"); + try { + let filePath: fs.File = fs.openSync(file); + let filePathFold = filePath.getParent(); + if (filePathFold.startsWith(this.shareCacheFolder())) { + return true; + } + } catch (err) { + Log.e(TAG, 'err:' + JSON.stringify(err)); + } + return false; + } + + private async clearShareCacheFolder(): Promise { + Log.i(TAG, "clearShareCacheFolder"); + try { + let folder: string = this.shareCacheFolder(); + if (fs.accessSync(folder)) { + let files = fs.listFileSync(folder); + if (files.length > 0) { + files.forEach(item => { + fs.unlinkSync(folder + '/' + item); + }) + fs.rmdirSync(folder); + } + } + } catch (err) { + Log.e(TAG, 'err:' + JSON.stringify(err)); + } + } + + private async copyToShareCacheFolder(file: string): Promise { + Log.i(TAG, "copyToShareCacheFolder"); + let folder = this.shareCacheFolder(); + if (!fs.accessSync(folder)) { + fs.mkdirSync(folder); + } + let oldFile: fs.File = fs.openSync(file); + let newFile = folder + '/' + oldFile.name; + fs.copyFileSync(oldFile.fd, newFile); + return newFile + } +} diff --git a/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/SharePlusOhosPlugin.ets b/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/SharePlusOhosPlugin.ets new file mode 100644 index 0000000000000000000000000000000000000000..1d598fc436705682e41f423ae39a13b2b9896360 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/ets/dev/fluttercommunity/plus/share/SharePlusOhosPlugin.ets @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import AbilityAware from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityAware'; +import { + AbilityPluginBinding +} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/ability/AbilityPluginBinding'; +import { + FlutterPlugin, + FlutterPluginBinding +} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; +import MethodChannel from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import Share from './Share'; +import MethodChannelHandlerImpl from './MethodChannelHandlerImpl'; + +const TAG = "SharePlusOhosPlugin"; +const CHANNEL_NAME = 'dev.fluttercommunity.plus/share'; + +export default class SharePlusOhosPlugin implements FlutterPlugin, AbilityAware { + private methodChannel: MethodChannel | null = null; + private methodChannelHandlerImpl: MethodChannelHandlerImpl | null = null; + private share: Share | null = null + + getUniqueClassName(): string { + return TAG; + } + + onAttachedToAbility(binding: AbilityPluginBinding) { + Log.i(TAG, "onAttachedToAbility"); + this.share?.setAbility(binding.getAbility()); + } + + onDetachedFromAbility() { + Log.i(TAG, "onDetachedFromAbility"); + this.share?.setAbility(null); + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + Log.i(TAG, "onAttachedToEngine"); + this.methodChannel = new MethodChannel(binding.getBinaryMessenger(), CHANNEL_NAME); + this.share = new Share(binding.getApplicationContext()); + this.methodChannelHandlerImpl = new MethodChannelHandlerImpl(this.share); + this.methodChannel.setMethodCallHandler(this.methodChannelHandlerImpl); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void { + Log.i(TAG, "onDetachedFromEngine"); + this.methodChannel?.setMethodCallHandler(null); + this.methodChannel = null; + } +} diff --git a/packages/share_plus/share_plus/ohos/src/main/module.json5 b/packages/share_plus/share_plus/ohos/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..bd73144ab980f092d53b555c0c368bfed52e88c2 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/module.json5 @@ -0,0 +1,24 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "share_plus", + "type": "har", + "deviceTypes": [ + "default", + ] + } +} diff --git a/packages/share_plus/share_plus/ohos/src/main/resources/base/element/color.json b/packages/share_plus/share_plus/ohos/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/ohos/src/main/resources/base/element/string.json b/packages/share_plus/share_plus/ohos/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..97bb8229977deacfc7ec791ea8db61dce2364334 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "share_plus" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/ohos/src/main/resources/base/media/icon.png b/packages/share_plus/share_plus/ohos/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/share_plus/share_plus/ohos/src/main/resources/base/media/icon.png differ diff --git a/packages/share_plus/share_plus/ohos/src/main/resources/base/profile/main_pages.json b/packages/share_plus/share_plus/ohos/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/packages/share_plus/share_plus/ohos/src/main/resources/en_US/element/string.json b/packages/share_plus/share_plus/ohos/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..97bb8229977deacfc7ec791ea8db61dce2364334 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "share_plus" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/ohos/src/main/resources/zh_CN/element/string.json b/packages/share_plus/share_plus/ohos/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..fda94088244ac6cbfe54708826ea34b1eb2ca205 --- /dev/null +++ b/packages/share_plus/share_plus/ohos/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "share_plus" + } + ] +} \ No newline at end of file diff --git a/packages/share_plus/share_plus/pubspec.yaml b/packages/share_plus/share_plus/pubspec.yaml index a1f382da2148ceafd2b1a6729061d4cc021eb6f7..7b7889fd6de6730c91186af3256baeea7a4b7b8c 100644 --- a/packages/share_plus/share_plus/pubspec.yaml +++ b/packages/share_plus/share_plus/pubspec.yaml @@ -26,7 +26,9 @@ flutter: windows: dartPluginClass: SharePlusWindowsPlugin pluginClass: SharePlusWindowsPluginCApi - + ohos: + package: dev.fluttercommunity.plus.share + pluginClass: SharePlusOhosPlugin dependencies: cross_file: ^0.3.4+2 meta: ^1.8.0 @@ -35,7 +37,8 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - share_plus_platform_interface: ^5.0.1 + share_plus_platform_interface: + path: ../share_plus_platform_interface file: ">=6.1.4 <8.0.0" url_launcher_web: ^2.3.2 url_launcher_windows: ^3.1.2 diff --git a/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart b/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart index bb7fa696c6437ba4640d366e793dd3dfc774c72f..271c90ad8e105b12585395957c4947eacdaed8ac 100644 --- a/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart +++ b/packages/share_plus/share_plus_platform_interface/lib/method_channel/method_channel_share.dart @@ -97,6 +97,7 @@ class MethodChannelShare extends SharePlatform { final params = { 'paths': paths, 'mimeTypes': mimeTypes, + "fileNameOverrides":fileNameOverrides }; if (subject != null) params['subject'] = subject; diff --git a/packages/share_plus/share_plus_platform_interface/pubspec.yaml b/packages/share_plus/share_plus_platform_interface/pubspec.yaml index 11080838d61c016fc3bbcfe878f192c08d81a150..a6957fd22e8d2d27ee4eba7748a4cefe22a45bcb 100644 --- a/packages/share_plus/share_plus_platform_interface/pubspec.yaml +++ b/packages/share_plus/share_plus_platform_interface/pubspec.yaml @@ -11,7 +11,11 @@ dependencies: meta: ^1.8.0 mime: ">=1.0.4 <3.0.0" plugin_platform_interface: ^2.1.4 - path_provider: ^2.0.14 + path_provider: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + ref: master + path: packages/path_provider/path_provider uuid: ">=3.0.7 <5.0.0" dev_dependencies: