diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee85b..ec97fc6f30 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee85b..c4855bfe20 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000000..5c4ba94685 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,40 @@ +platform :ios, '11.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/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000000..967e20106d --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - Flutter (1.0.0) + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - share_plus (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - share_plus (from `.symlinks/plugins/share_plus/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + share_plus: + :path: ".symlinks/plugins/share_plus/ios" + +SPEC CHECKSUMS: + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 + share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 + +PODFILE CHECKSUM: 985e5b058f26709dc81f9ae74ea2b2775bdbcefe + +COCOAPODS: 1.11.3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 328e4294ab..fe0dc7d302 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/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 */; }; + F311C174AF9C005CE4AADD72 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EAE3F3F518B95B7BFEB4FE7 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -31,9 +32,13 @@ /* 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 = ""; }; + 157DB5307E82FD55510A52F6 /* 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 = ""; }; + 3EAE3F3F518B95B7BFEB4FE7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4541FE48FEFD549440B32652 /* 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 = ""; }; 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 = ""; }; + 7A94C3F14B90E7FC7BC4B082 /* 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 = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -49,12 +54,24 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F311C174AF9C005CE4AADD72 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 876166F6347BF9C555764E5A /* Pods */ = { + isa = PBXGroup; + children = ( + 157DB5307E82FD55510A52F6 /* Pods-Runner.debug.xcconfig */, + 4541FE48FEFD549440B32652 /* Pods-Runner.release.xcconfig */, + 7A94C3F14B90E7FC7BC4B082 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -72,6 +89,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + 876166F6347BF9C555764E5A /* Pods */, + DE33BFABA662D9225C39B5E5 /* Frameworks */, ); sourceTree = ""; }; @@ -98,6 +117,14 @@ path = Runner; sourceTree = ""; }; + DE33BFABA662D9225C39B5E5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3EAE3F3F518B95B7BFEB4FE7 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -105,12 +132,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 6B657AD6067C1F92BC2172DC /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + CF082B7052F068E927BF3A60 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -185,6 +214,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 6B657AD6067C1F92BC2172DC /* [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; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -200,6 +251,23 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + CF082B7052F068E927BF3A60 /* [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; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed..21a3cc14c7 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/lib/widgets/action_sheet.dart b/lib/widgets/action_sheet.dart new file mode 100644 index 0000000000..740684a193 --- /dev/null +++ b/lib/widgets/action_sheet.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:share_plus/share_plus.dart'; + +import '../api/model/model.dart'; +import 'draggable_scrollable_modal_bottom_sheet.dart'; + +void showMessageActionSheet({required BuildContext context, required Message message}) { + showDraggableScrollableModalBottomSheet( + context: context, + builder: (BuildContext context) { + return Column( + children: [ + MenuItemButton( + leadingIcon: Icon(Icons.adaptive.share), + onPressed: () async { + // Close the message action sheet; we're about to show the share + // sheet. (We could do this after the sharing Future settles, but + // on iOS I get impatient with how slowly our action sheet + // dismisses in that case.) + // TODO(#24): Fix iOS bug where this call causes the keyboard to + // reopen (if it was open at the time of this + // `showMessageActionSheet` call) and cover a large part of the + // share sheet. + Navigator.of(context).pop(); + + // TODO: to support iPads, we're asked to give a + // `sharePositionOrigin` param, or risk crashing / hanging: + // https://pub.dev/packages/share_plus#ipad + // Perhaps a wart in the API; discussion: + // https://github.com/zulip/zulip-flutter/pull/12#discussion_r1130146231 + // TODO: Share raw Markdown, not HTML + await Share.shareWithResult(message.content); + }, + child: const Text('Share'), + ), + ] + ); + }); +} diff --git a/lib/widgets/draggable_scrollable_modal_bottom_sheet.dart b/lib/widgets/draggable_scrollable_modal_bottom_sheet.dart new file mode 100644 index 0000000000..6e3237407b --- /dev/null +++ b/lib/widgets/draggable_scrollable_modal_bottom_sheet.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; + +class _DraggableScrollableLayer extends StatelessWidget { + const _DraggableScrollableLayer({required this.builder}); + + final WidgetBuilder builder; + + @override + Widget build(BuildContext context) { + return DraggableScrollableSheet( + // Match `initial…` to `min…` so that a slight drag downward dismisses + // the sheet instead of just resizing it. Making them equal gives a + // buggy experience for some reason + // ( https://github.com/zulip/zulip-flutter/pull/12#discussion_r1116423455 ) + // so we work around by make `initial…` a bit bigger. + minChildSize: 0.25, + initialChildSize: 0.26, + + // With `expand: true`, the bottom sheet would then start out occupying + // the whole screen, as if `initialChildSize` was 1.0. That doesn't seem + // like what the docs call for. Maybe a bug. Or maybe it's somehow + // related to the `Stack`? + expand: false, + + builder: (BuildContext context, ScrollController scrollController) { + return SingleChildScrollView( + // Prevent overscroll animation on swipe down; it looks + // sloppy when you're swiping to dismiss the sheet. + physics: const ClampingScrollPhysics(), + + controller: scrollController, + + child: Padding( + // Avoid the drag handle. See comment on + // _DragHandleLayer's SizedBox.height. + padding: const EdgeInsets.only(top: kMinInteractiveDimension), + + // Extend DraggableScrollableSheet to full width so the whole + // sheet responds to drag/scroll uniformly. + child: FractionallySizedBox( + widthFactor: 1.0, + child: Builder(builder: builder), + ), + ), + ); + }); + } +} + +class _DragHandleLayer extends StatelessWidget { + @override + Widget build(BuildContext context) { + ColorScheme colorScheme = Theme.of(context).colorScheme; + return SizedBox( + // In the spec, this is expressed as 22 logical pixels of top/bottom + // padding on the drag handle: + // https://m3.material.io/components/bottom-sheets/specs#e69f3dfb-e443-46ba-b4a8-aabc718cf335 + // The drag handle is specified with height 4 logical pixels, so we can + // get the same result by vertically centering the handle in a box with + // height 22 + 4 + 22 = 48. We have another way to say 48 -- + // kMinInteractiveDimension -- which is actually not a bad way to + // express it, since the feature was announced as "an optional drag + // handle with an accessible 48dp hit target": + // https://m3.material.io/components/bottom-sheets/overview#2cce5bae-eb83-40b0-8e52-5d0cfaa9b795 + // As a bonus, that constant is easy to use at the other layer in the + // Stack where we set the starting position of the sheet's content to + // avoid the drag handle. + height: kMinInteractiveDimension, + + child: Center( + child: ClipRRect( + clipBehavior: Clip.hardEdge, + borderRadius: const BorderRadius.all(Radius.circular(2)), + child: SizedBox( + // height / width / color (including opacity) from this table: + // https://m3.material.io/components/bottom-sheets/specs#7c093473-d9e1-48f3-9659-b75519c2a29d + height: 4, + width: 32, + child: ColoredBox(color: colorScheme.onSurfaceVariant.withOpacity(0.40)), + ), + ))); + } +} + +/// Show a modal bottom sheet that drags and scrolls to present lots of content. +/// +/// Aims to follow Material 3's "bottom sheet" with a drag handle: +/// https://m3.material.io/components/bottom-sheets/overview +Future showDraggableScrollableModalBottomSheet({ + required BuildContext context, + required WidgetBuilder builder, +}) { + return showModalBottomSheet( + context: context, + + // Clip.hardEdge looks bad; Clip.antiAliasWithSaveLayer looks pixel-perfect + // on my iPhone 13 Pro but is marked as "much slower": + // https://api.flutter.dev/flutter/dart-ui/Clip.html + clipBehavior: Clip.antiAlias, + + // The spec: + // https://m3.material.io/components/bottom-sheets/specs + // defines the container's shape with the design token + // `md.sys.shape.corner.extra-large.top`, which in the table at + // https://m3.material.io/styles/shape/shape-scale-tokens#6f668ba1-b671-4ea2-bcf3-c1cff4f4099e + // maps to: + // 28dp,28dp,0dp,0dp + // SHAPE_FAMILY_ROUNDED_CORNERS + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(28.0))), + + useSafeArea: true, + isScrollControlled: true, + builder: (BuildContext context) { + // Make the content start below the drag handle in the y-direction, but + // when the content is scrollable, let it scroll under the drag handle in + // the z-direction. + return Stack( + children: [ + _DraggableScrollableLayer(builder: builder), + _DragHandleLayer(), + ], + ); + }); +} diff --git a/lib/widgets/message_list.dart b/lib/widgets/message_list.dart index 27c328a62d..c665408080 100644 --- a/lib/widgets/message_list.dart +++ b/lib/widgets/message_list.dart @@ -7,6 +7,7 @@ import '../model/content.dart'; import '../model/message_list.dart'; import '../model/narrow.dart'; import '../model/store.dart'; +import 'action_sheet.dart'; import 'content.dart'; import 'sticky_header.dart'; import 'store.dart'; @@ -300,35 +301,39 @@ class MessageWithSender extends StatelessWidget { final time = _kMessageTimestampFormat .format(DateTime.fromMillisecondsSinceEpoch(1000 * message.timestamp)); - // TODO clean up this layout, by less precisely imitating web - return Padding( - padding: const EdgeInsets.only(top: 2, bottom: 3, left: 8, right: 8), - child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: const EdgeInsets.fromLTRB(3, 6, 11, 0), - child: Container( - clipBehavior: Clip.antiAlias, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4))), - width: 35, - height: 35, - child: avatar)), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 3), - Text(message.sender_full_name, // TODO get from user data - style: const TextStyle(fontWeight: FontWeight.bold)), - const SizedBox(height: 4), - MessageContent(message: message, content: content), - ])), - Container( - width: 80, - padding: const EdgeInsets.only(top: 4, right: 2), - alignment: Alignment.topRight, - child: Text(time, style: _kMessageTimestampStyle)) - ])); + return GestureDetector( + behavior: HitTestBehavior.translucent, + onLongPress: () => showMessageActionSheet(context: context, message: message), + // TODO clean up this layout, by less precisely imitating web + child: Padding( + padding: const EdgeInsets.only(top: 2, bottom: 3, left: 8, right: 8), + child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: const EdgeInsets.fromLTRB(3, 6, 11, 0), + child: Container( + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(4))), + width: 35, + height: 35, + child: avatar)), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 3), + Text(message.sender_full_name, // TODO get from user data + style: const TextStyle(fontWeight: FontWeight.bold)), + const SizedBox(height: 4), + MessageContent(message: message, content: content), + ])), + Container( + width: 80, + padding: const EdgeInsets.only(top: 4, right: 2), + alignment: Alignment.topRight, + child: Text(time, style: _kMessageTimestampStyle)) + ])), + ); } } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d23d..f6f23bfe97 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87a7e..f16b4c3421 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b608..4b81f9b2d2 100644 --- a/macos/Flutter/Flutter-Debug.xcconfig +++ b/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/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig index c2efd0b608..5caa9d1579 100644 --- a/macos/Flutter/Flutter-Release.xcconfig +++ b/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/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817a52..17f9da9c01 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,10 @@ import FlutterMacOS import Foundation +import path_provider_foundation +import share_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) } diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000000..049abe2954 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.14' + +# 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/macos/Podfile.lock b/macos/Podfile.lock new file mode 100644 index 0000000000..6ccf4a0e71 --- /dev/null +++ b/macos/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - FlutterMacOS (1.0.0) + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - share_plus (0.0.1): + - FlutterMacOS + +DEPENDENCIES: + - FlutterMacOS (from `Flutter/ephemeral`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) + - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) + +EXTERNAL SOURCES: + FlutterMacOS: + :path: Flutter/ephemeral + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin + share_plus: + :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos + +SPEC CHECKSUMS: + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 + share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7 + +PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 + +COCOAPODS: 1.11.3 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 2d1c598d67..2cb009e601 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/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 */; }; + EEDE12ED9FD25583D39369CA /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C3D9D844421A2A87767F4C8 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1A6844CABCD767C3D34B3277 /* 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 = ""; }; 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 /* zulip.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "zulip.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* zulip.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = zulip.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 = ""; }; @@ -66,8 +68,11 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 4ADDD444D9EC96A7EDC27F55 /* 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 = ""; }; + 4C3D9D844421A2A87767F4C8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 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 = ""; }; + EEFD4A182C0178D39707F294 /* 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,12 +80,24 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EEDE12ED9FD25583D39369CA /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0F3BBA1B2530E5A508861851 /* Pods */ = { + isa = PBXGroup; + children = ( + EEFD4A182C0178D39707F294 /* Pods-Runner.debug.xcconfig */, + 4ADDD444D9EC96A7EDC27F55 /* Pods-Runner.release.xcconfig */, + 1A6844CABCD767C3D34B3277 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -99,6 +116,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 0F3BBA1B2530E5A508861851 /* Pods */, ); sourceTree = ""; }; @@ -148,6 +166,7 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 4C3D9D844421A2A87767F4C8 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 9F4813DCFCBCB3009D166429 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + FD4A0BBCC328170C90F9011D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -271,6 +292,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 9F4813DCFCBCB3009D166429 /* [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; + }; + FD4A0BBCC328170C90F9011D /* [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; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed..21a3cc14c7 100644 --- a/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/pubspec.lock b/pubspec.lock index 8ff1657685..3c29011fcd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -169,6 +169,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.6.3" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" + source: hosted + version: "0.3.3+4" crypto: dependency: transitive description: @@ -209,6 +217,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" + source: hosted + version: "2.0.1" file: dependency: transitive description: @@ -243,6 +259,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" frontend_server_client: dependency: transitive description: @@ -391,10 +412,10 @@ packages: dependency: transitive description: name: node_preamble - sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" package_config: dependency: transitive description: @@ -411,6 +432,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" + url: "https://pub.dev" + source: hosted + version: "2.0.13" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e" + url: "https://pub.dev" + source: hosted + version: "2.0.23" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" + url: "https://pub.dev" + source: hosted + version: "2.1.9" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + url: "https://pub.dev" + source: hosted + version: "2.1.4" pool: dependency: transitive description: @@ -419,6 +504,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" pub_semver: dependency: transitive description: @@ -435,6 +528,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "8c6892037b1824e2d7e8f59d54b3105932899008642e6372e5079c6939b4b625" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "82ddd4ab9260c295e6e39612d4ff00390b9a7a21f1bb1da771e2f232d80ab8a1" + url: "https://pub.dev" + source: hosted + version: "3.2.0" shelf: dependency: transitive description: @@ -592,6 +701,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b" + url: "https://pub.dev" + source: hosted + version: "2.0.15" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b" + url: "https://pub.dev" + source: hosted + version: "3.0.4" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" vector_math: dependency: transitive description: @@ -632,6 +781,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + win32: + dependency: transitive + description: + name: win32 + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + url: "https://pub.dev" + source: hosted + version: "3.1.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + url: "https://pub.dev" + source: hosted + version: "1.0.0" yaml: dependency: transitive description: @@ -641,5 +806,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=3.0.0-277.0.dev <4.0.0" - flutter: ">=3.8.0-17.0.pre.49" + dart: ">=3.0.0-313.0.dev <4.0.0" + flutter: ">=3.9.0-1.0.pre.157" diff --git a/pubspec.yaml b/pubspec.yaml index 6895ba6589..31b0ab56ee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -24,8 +24,8 @@ environment: # that by the time we want to release, these will have become stable. # TODO: Before general release, switch to stable Flutter and Dart versions, # or pin exact versions: https://github.com/zulip/zulip-flutter/issues/15 - sdk: '>=3.0.0-277.0.dev <4.0.0' - flutter: '>=3.8.0-17.0.pre.49' + sdk: '>=3.0.0-313.0.dev <4.0.0' + flutter: '>=3.9.0-1.0.pre.157' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -45,6 +45,7 @@ dependencies: http: ^0.13.5 html: ^0.15.1 intl: ^0.18.0 + share_plus: ^6.3.1 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d4680af..c3384ec523 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,12 @@ #include "generated_plugin_registrant.h" +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b93c4c30c1..01d383628b 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + share_plus + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST