feat(channels): inline-кнопки под постами в каналах
This commit is contained in:
@@ -20,7 +20,5 @@
|
|||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
|
||||||
<string>13.0</string>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
+155
-8
@@ -1,62 +1,209 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- app_links (7.0.0):
|
||||||
|
- Flutter
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- DKImagePickerController/Core (4.3.9):
|
||||||
|
- DKImagePickerController/ImageDataManager
|
||||||
|
- DKImagePickerController/Resource
|
||||||
|
- DKImagePickerController/ImageDataManager (4.3.9)
|
||||||
|
- DKImagePickerController/PhotoGallery (4.3.9):
|
||||||
|
- DKImagePickerController/Core
|
||||||
|
- DKPhotoGallery
|
||||||
|
- DKImagePickerController/Resource (4.3.9)
|
||||||
|
- DKPhotoGallery (0.0.19):
|
||||||
|
- DKPhotoGallery/Core (= 0.0.19)
|
||||||
|
- DKPhotoGallery/Model (= 0.0.19)
|
||||||
|
- DKPhotoGallery/Preview (= 0.0.19)
|
||||||
|
- DKPhotoGallery/Resource (= 0.0.19)
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Core (0.0.19):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Preview
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Model (0.0.19):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Preview (0.0.19):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Resource
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Resource (0.0.19):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- file_picker (0.0.1):
|
||||||
|
- DKImagePickerController/PhotoGallery
|
||||||
|
- Flutter
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- flutter_inappwebview_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- flutter_inappwebview_ios/Core (= 0.0.1)
|
||||||
|
- OrderedSet (~> 6.0.3)
|
||||||
|
- flutter_inappwebview_ios/Core (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- OrderedSet (~> 6.0.3)
|
||||||
|
- flutter_local_notifications (0.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_secure_storage_darwin (10.0.0):
|
- flutter_secure_storage_darwin (10.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- flutter_timezone (0.0.1):
|
- flutter_timezone (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- flutter_webrtc (1.4.0):
|
||||||
|
- Flutter
|
||||||
|
- WebRTC-SDK (= 144.7559.09)
|
||||||
|
- geolocator_apple (1.2.0):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- media_kit_video (0.0.1):
|
||||||
|
- Flutter
|
||||||
- mobile_scanner (7.0.0):
|
- mobile_scanner (7.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- ogg_opus_player (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- open_filex (0.0.2):
|
||||||
|
- Flutter
|
||||||
|
- OrderedSet (6.0.3)
|
||||||
- package_info_plus (0.4.5):
|
- package_info_plus (0.4.5):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- photo_manager (3.9.0):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- record_ios (1.2.1):
|
||||||
|
- Flutter
|
||||||
|
- SDWebImage (5.21.7):
|
||||||
|
- SDWebImage/Core (= 5.21.7)
|
||||||
|
- SDWebImage/Core (5.21.7)
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqflite_darwin (0.0.4):
|
- sqflite_darwin (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- SwiftyGif (5.4.5)
|
||||||
|
- url_launcher_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- video_player_avfoundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- wakelock_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- WebRTC-SDK (144.7559.09)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||||
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
||||||
- flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`)
|
- flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`)
|
||||||
|
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
|
||||||
|
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
|
||||||
|
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
||||||
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
|
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
|
||||||
|
- ogg_opus_player (from `.symlinks/plugins/ogg_opus_player/darwin`)
|
||||||
|
- open_filex (from `.symlinks/plugins/open_filex/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
|
- photo_manager (from `.symlinks/plugins/photo_manager/darwin`)
|
||||||
|
- record_ios (from `.symlinks/plugins/record_ios/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||||
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||||
|
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- DKImagePickerController
|
||||||
|
- DKPhotoGallery
|
||||||
|
- OrderedSet
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- WebRTC-SDK
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
app_links:
|
||||||
|
:path: ".symlinks/plugins/app_links/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
|
file_picker:
|
||||||
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
flutter_inappwebview_ios:
|
||||||
|
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||||
|
flutter_local_notifications:
|
||||||
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
flutter_secure_storage_darwin:
|
flutter_secure_storage_darwin:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
||||||
flutter_timezone:
|
flutter_timezone:
|
||||||
:path: ".symlinks/plugins/flutter_timezone/ios"
|
:path: ".symlinks/plugins/flutter_timezone/ios"
|
||||||
|
flutter_webrtc:
|
||||||
|
:path: ".symlinks/plugins/flutter_webrtc/ios"
|
||||||
|
geolocator_apple:
|
||||||
|
:path: ".symlinks/plugins/geolocator_apple/darwin"
|
||||||
|
media_kit_video:
|
||||||
|
:path: ".symlinks/plugins/media_kit_video/ios"
|
||||||
mobile_scanner:
|
mobile_scanner:
|
||||||
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
||||||
|
ogg_opus_player:
|
||||||
|
:path: ".symlinks/plugins/ogg_opus_player/darwin"
|
||||||
|
open_filex:
|
||||||
|
:path: ".symlinks/plugins/open_filex/ios"
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
|
photo_manager:
|
||||||
|
:path: ".symlinks/plugins/photo_manager/darwin"
|
||||||
|
record_ios:
|
||||||
|
:path: ".symlinks/plugins/record_ios/ios"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
sqflite_darwin:
|
sqflite_darwin:
|
||||||
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
||||||
|
url_launcher_ios:
|
||||||
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
video_player_avfoundation:
|
||||||
|
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
|
||||||
|
wakelock_plus:
|
||||||
|
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
|
app_links: a754cbec3c255bd4bbb4d236ecc06f28cd9a7ce8
|
||||||
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
|
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_secure_storage_darwin: 557817588b80e60213cbecb573c45c76b788018d
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_timezone: ac3da59ac941ff1c98a2e1f0293420e020120282
|
flutter_local_notifications: 643a3eda1ce1c0599413ca31672536d423dee214
|
||||||
mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e
|
flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23
|
||||||
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
|
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||||
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
flutter_webrtc: 3ee86aa10e0313c38c93fdb215dd86e77014f96a
|
||||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
|
||||||
|
media_kit_video: f3b0d035d89def15cfbbcf7dc2ae278f201e2f83
|
||||||
|
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
|
||||||
|
ogg_opus_player: 954784304f4e2722780018c4abf284e4f93cddf5
|
||||||
|
open_filex: 432f3cd11432da3e39f47fcc0df2b1603854eff1
|
||||||
|
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||||
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
|
photo_manager: 25fd77df14f4f0ba5ef99e2c61814dde77e2bceb
|
||||||
|
record_ios: 980fd386a97a35987d0fce3dfda4b26a38c90f4c
|
||||||
|
SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
|
||||||
|
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||||
|
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||||
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
|
video_player_avfoundation: 3453f792138786248960ca029747fcd9f318ef52
|
||||||
|
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||||
|
WebRTC-SDK: e6006119cd730d6315d875e4a421b6cc8bb88833
|
||||||
|
|
||||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
PODFILE CHECKSUM: 527e8cb59c3d722cc71f78b05ab13f192b9335d3
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
B1B2C3D41234567890ABCDEF /* MinimalIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A1B2C3D41234567890ABCDEF /* MinimalIcon@2x.png */; };
|
B1B2C3D41234567890ABCDEF /* MinimalIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A1B2C3D41234567890ABCDEF /* MinimalIcon@2x.png */; };
|
||||||
B1B2C3D41234567890ABCDF0 /* MinimalIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = A1B2C3D41234567890ABCDF0 /* MinimalIcon@3x.png */; };
|
B1B2C3D41234567890ABCDF0 /* MinimalIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = A1B2C3D41234567890ABCDF0 /* MinimalIcon@3x.png */; };
|
||||||
E835CC948F2F948DC3BBF405 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AE8CB2654009FE276CACA4B /* Pods_RunnerTests.framework */; };
|
E835CC948F2F948DC3BBF405 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AE8CB2654009FE276CACA4B /* Pods_RunnerTests.framework */; };
|
||||||
|
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -69,6 +70,7 @@
|
|||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
9D7B0FFE63E0BD5D67D7758D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
9D7B0FFE63E0BD5D67D7758D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -84,6 +86,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
||||||
4B1A4BBCD56B3CE42AD0A480 /* Pods_Runner.framework in Frameworks */,
|
4B1A4BBCD56B3CE42AD0A480 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@@ -111,6 +114,7 @@
|
|||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||||
@@ -194,6 +198,9 @@
|
|||||||
productType = "com.apple.product-type.bundle.unit-test";
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
};
|
};
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
|
packageProductDependencies = (
|
||||||
|
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
|
||||||
|
);
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
@@ -219,6 +226,9 @@
|
|||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
|
packageReferences = (
|
||||||
|
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
|
||||||
|
);
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = YES;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
@@ -731,6 +741,18 @@
|
|||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
/* Begin XCLocalSwiftPackageReference section */
|
||||||
|
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
|
||||||
|
isa = XCLocalSwiftPackageReference;
|
||||||
|
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
||||||
|
};
|
||||||
|
/* End XCLocalSwiftPackageReference section */
|
||||||
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = FlutterGeneratedPluginSwiftPackage;
|
||||||
|
};
|
||||||
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,24 @@
|
|||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
buildImplicitDependencies = "YES">
|
buildImplicitDependencies = "YES">
|
||||||
|
<PreActions>
|
||||||
|
<ExecutionAction
|
||||||
|
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||||
|
<ActionContent
|
||||||
|
title = "Run Prepare Flutter Framework Script"
|
||||||
|
scriptText = "/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare ">
|
||||||
|
<EnvironmentBuildable>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</EnvironmentBuildable>
|
||||||
|
</ActionContent>
|
||||||
|
</ExecutionAction>
|
||||||
|
</PreActions>
|
||||||
<BuildActionEntries>
|
<BuildActionEntries>
|
||||||
<BuildActionEntry
|
<BuildActionEntry
|
||||||
buildForTesting = "YES"
|
buildForTesting = "YES"
|
||||||
|
|||||||
@@ -333,6 +333,8 @@ class ReplyInfo {
|
|||||||
return 'Ссылка';
|
return 'Ссылка';
|
||||||
case AttachmentType.control:
|
case AttachmentType.control:
|
||||||
return '';
|
return '';
|
||||||
|
case AttachmentType.inlineKeyboard:
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
@@ -871,6 +873,28 @@ class MessagesModule {
|
|||||||
return response.isOk;
|
return response.isOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>?> sendButtonCallback({
|
||||||
|
required int chatId,
|
||||||
|
required String messageId,
|
||||||
|
required String callbackId,
|
||||||
|
String? payload,
|
||||||
|
}) async {
|
||||||
|
final mid = int.tryParse(messageId);
|
||||||
|
if (mid == null) return null;
|
||||||
|
|
||||||
|
final request = {
|
||||||
|
'chatId': chatId,
|
||||||
|
'messageId': mid,
|
||||||
|
'callbackId': callbackId,
|
||||||
|
'payload': ?payload,
|
||||||
|
};
|
||||||
|
|
||||||
|
final response = await _api.sendRequest(Opcode.msgSendCallback, request);
|
||||||
|
if (!response.isOk) return null;
|
||||||
|
final data = response.payload;
|
||||||
|
return data is Map ? Map<String, dynamic>.from(data) : null;
|
||||||
|
}
|
||||||
|
|
||||||
Future<TranscriptionResult> requestTranscription(
|
Future<TranscriptionResult> requestTranscription(
|
||||||
int chatId,
|
int chatId,
|
||||||
int messageId,
|
int messageId,
|
||||||
|
|||||||
@@ -24,12 +24,18 @@ class WebAppModule {
|
|||||||
|
|
||||||
WebAppModule(this._api);
|
WebAppModule(this._api);
|
||||||
|
|
||||||
Future<WebAppLaunch> fetchLaunch(int botId) async {
|
Future<WebAppLaunch> fetchLaunch(
|
||||||
|
int botId, {
|
||||||
|
String? startParam,
|
||||||
|
int? chatId,
|
||||||
|
}) async {
|
||||||
if (_api.state != SessionState.online) {
|
if (_api.state != SessionState.online) {
|
||||||
throw const WebAppUnavailable('Нет соединения с сервером');
|
throw const WebAppUnavailable('Нет соединения с сервером');
|
||||||
}
|
}
|
||||||
final packet = await _api.sendRequest(Opcode.webAppInitData, {
|
final packet = await _api.sendRequest(Opcode.webAppInitData, {
|
||||||
'botId': botId,
|
'botId': botId,
|
||||||
|
'startParam': ?startParam,
|
||||||
|
'chatId': ?chatId,
|
||||||
});
|
});
|
||||||
if (!packet.isOk) {
|
if (!packet.isOk) {
|
||||||
throw const WebAppUnavailable('Не удалось открыть мини-приложение');
|
throw const WebAppUnavailable('Не удалось открыть мини-приложение');
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:flutter/rendering.dart';
|
|||||||
import 'package:komet/main.dart';
|
import 'package:komet/main.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import '../../backend/modules/messages.dart';
|
import '../../backend/modules/messages.dart';
|
||||||
|
import '../screens/webapp/web_app_screen.dart';
|
||||||
import '../../core/config/app_bubble_behavior.dart';
|
import '../../core/config/app_bubble_behavior.dart';
|
||||||
import '../../core/config/app_bubble_shape.dart';
|
import '../../core/config/app_bubble_shape.dart';
|
||||||
import '../../core/config/komet_settings.dart';
|
import '../../core/config/komet_settings.dart';
|
||||||
@@ -194,9 +195,20 @@ class MessageBubble extends StatelessWidget {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InlineKeyboardAttachment? get _inlineKeyboard {
|
||||||
|
final attachments = message.attachments;
|
||||||
|
if (attachments == null) return null;
|
||||||
|
for (final a in attachments) {
|
||||||
|
if (a is InlineKeyboardAttachment && !a.isEmpty) return a;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
MessageType _computeContentType() {
|
MessageType _computeContentType() {
|
||||||
if (message.isControl) return MessageType.control;
|
if (message.isControl) return MessageType.control;
|
||||||
final attachments = message.attachments;
|
final attachments = message.attachments
|
||||||
|
?.where((a) => a is! InlineKeyboardAttachment)
|
||||||
|
.toList();
|
||||||
if (attachments != null && attachments.isNotEmpty) {
|
if (attachments != null && attachments.isNotEmpty) {
|
||||||
final first = attachments.first;
|
final first = attachments.first;
|
||||||
if (first is ForwardedMessageAttachment) {
|
if (first is ForwardedMessageAttachment) {
|
||||||
@@ -433,6 +445,7 @@ class MessageBubble extends StatelessWidget {
|
|||||||
prevMessage?.senderId != message.senderId;
|
prevMessage?.senderId != message.senderId;
|
||||||
|
|
||||||
final maxBubbleWidth = MediaQuery.sizeOf(context).width * 0.75;
|
final maxBubbleWidth = MediaQuery.sizeOf(context).width * 0.75;
|
||||||
|
final keyboard = _inlineKeyboard;
|
||||||
final isVideoNote = _isVideoNote;
|
final isVideoNote = _isVideoNote;
|
||||||
final bubbleColor = isVideoNote
|
final bubbleColor = isVideoNote
|
||||||
? Colors.transparent
|
? Colors.transparent
|
||||||
@@ -553,6 +566,11 @@ class MessageBubble extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (keyboard != null)
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: maxBubbleWidth),
|
||||||
|
child: _buildInlineKeyboard(context, cs, keyboard),
|
||||||
|
),
|
||||||
if (reactionsUnder) _reactionsBar(cs),
|
if (reactionsUnder) _reactionsBar(cs),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -562,6 +580,169 @@ class MessageBubble extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildInlineKeyboard(
|
||||||
|
BuildContext context,
|
||||||
|
ColorScheme cs,
|
||||||
|
InlineKeyboardAttachment keyboard,
|
||||||
|
) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 4),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
for (final row in keyboard.rows)
|
||||||
|
if (row.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
for (var i = 0; i < row.length; i++) ...[
|
||||||
|
if (i > 0) const SizedBox(width: 4),
|
||||||
|
Expanded(
|
||||||
|
child: _buildInlineKeyboardButton(
|
||||||
|
context,
|
||||||
|
cs,
|
||||||
|
keyboard,
|
||||||
|
row[i],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInlineKeyboardButton(
|
||||||
|
BuildContext context,
|
||||||
|
ColorScheme cs,
|
||||||
|
InlineKeyboardAttachment keyboard,
|
||||||
|
InlineKeyboardButton button,
|
||||||
|
) {
|
||||||
|
final trailingIcon = switch (button.type) {
|
||||||
|
'LINK' => Symbols.open_in_new,
|
||||||
|
'OPEN_APP' => Symbols.chevron_right,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
return Material(
|
||||||
|
color: cs.primary.withValues(alpha: 0.12),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => _onInlineButtonTap(context, keyboard, button),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
button.text,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
color: cs.primary,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (trailingIcon != null) ...[
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Icon(trailingIcon, size: 16, color: cs.primary),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onInlineButtonTap(
|
||||||
|
BuildContext context,
|
||||||
|
InlineKeyboardAttachment keyboard,
|
||||||
|
InlineKeyboardButton button,
|
||||||
|
) async {
|
||||||
|
switch (button.type) {
|
||||||
|
case 'LINK':
|
||||||
|
final url = button.url;
|
||||||
|
if (url != null && url.isNotEmpty) {
|
||||||
|
await openExternalUrl(context, url);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 'OPEN_APP':
|
||||||
|
await _openMiniApp(context, button);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
final callbackId = keyboard.callbackId;
|
||||||
|
if (callbackId == null || callbackId.isEmpty) {
|
||||||
|
showCustomNotification(context, 'Кнопка не поддерживается');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final answer = await messagesModule.sendButtonCallback(
|
||||||
|
chatId: message.chatId,
|
||||||
|
messageId: message.id,
|
||||||
|
callbackId: callbackId,
|
||||||
|
payload: button.payload,
|
||||||
|
);
|
||||||
|
if (!context.mounted) return;
|
||||||
|
final url = answer?['url']?.toString();
|
||||||
|
if (url != null && url.isNotEmpty) {
|
||||||
|
await openExternalUrl(context, url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final text = answer?['text']?.toString();
|
||||||
|
if (text != null && text.isNotEmpty) {
|
||||||
|
showCustomNotification(context, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _openMiniApp(
|
||||||
|
BuildContext context,
|
||||||
|
InlineKeyboardButton button,
|
||||||
|
) async {
|
||||||
|
final deeplink = button.webApp != null
|
||||||
|
? Uri.tryParse(button.webApp!)
|
||||||
|
: null;
|
||||||
|
final startParam =
|
||||||
|
button.payload ??
|
||||||
|
deeplink?.queryParameters['startapp'] ??
|
||||||
|
deeplink?.queryParameters['startApp'];
|
||||||
|
final chatId =
|
||||||
|
int.tryParse(deeplink?.queryParameters['chat_id'] ?? '') ??
|
||||||
|
message.chatId;
|
||||||
|
final botId = button.contactId;
|
||||||
|
|
||||||
|
if (botId == null) {
|
||||||
|
showCustomNotification(context, 'Не удалось открыть приложение');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
'[inline-kb] OPEN_APP botId=$botId chatId=$chatId startParam=$startParam',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (_) => WebAppScreen(
|
||||||
|
title: button.text,
|
||||||
|
loader: () => webAppModule.fetchLaunch(
|
||||||
|
botId,
|
||||||
|
startParam: startParam,
|
||||||
|
chatId: chatId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Map? _resolveReactionInfo() {
|
Map? _resolveReactionInfo() {
|
||||||
if (reactionsListenable != null) {
|
if (reactionsListenable != null) {
|
||||||
final v = reactionsListenable!.value;
|
final v = reactionsListenable!.value;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ enum AttachmentType {
|
|||||||
poll,
|
poll,
|
||||||
share,
|
share,
|
||||||
call,
|
call,
|
||||||
|
inlineKeyboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
String? decodeAttachPreview(dynamic raw) {
|
String? decodeAttachPreview(dynamic raw) {
|
||||||
@@ -64,7 +65,7 @@ abstract class MessageAttachment {
|
|||||||
case 'SHARE':
|
case 'SHARE':
|
||||||
return ShareAttachment.fromMap(map);
|
return ShareAttachment.fromMap(map);
|
||||||
case 'INLINE_KEYBOARD':
|
case 'INLINE_KEYBOARD':
|
||||||
return UnknownAttachment(map);
|
return InlineKeyboardAttachment.fromMap(map);
|
||||||
default:
|
default:
|
||||||
return UnknownAttachment(map);
|
return UnknownAttachment(map);
|
||||||
}
|
}
|
||||||
@@ -580,6 +581,93 @@ class ShareAttachment extends MessageAttachment {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class InlineKeyboardButton {
|
||||||
|
final String type;
|
||||||
|
final String text;
|
||||||
|
final String? url;
|
||||||
|
final String? webApp;
|
||||||
|
final int? contactId;
|
||||||
|
final String? payload;
|
||||||
|
|
||||||
|
const InlineKeyboardButton({
|
||||||
|
required this.type,
|
||||||
|
required this.text,
|
||||||
|
this.url,
|
||||||
|
this.webApp,
|
||||||
|
this.contactId,
|
||||||
|
this.payload,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory InlineKeyboardButton.fromMap(Map<String, dynamic> map) {
|
||||||
|
return InlineKeyboardButton(
|
||||||
|
type: (map['type'] as String? ?? '').toUpperCase(),
|
||||||
|
text: map['text']?.toString() ?? '',
|
||||||
|
url: map['url']?.toString(),
|
||||||
|
webApp: map['webApp']?.toString(),
|
||||||
|
contactId: map['contactId'] is int
|
||||||
|
? map['contactId'] as int
|
||||||
|
: int.tryParse(map['contactId']?.toString() ?? ''),
|
||||||
|
payload: map['payload']?.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() => {
|
||||||
|
'type': type,
|
||||||
|
'text': text,
|
||||||
|
if (url != null) 'url': url,
|
||||||
|
if (webApp != null) 'webApp': webApp,
|
||||||
|
if (contactId != null) 'contactId': contactId,
|
||||||
|
if (payload != null) 'payload': payload,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class InlineKeyboardAttachment extends MessageAttachment {
|
||||||
|
final String? callbackId;
|
||||||
|
final List<List<InlineKeyboardButton>> rows;
|
||||||
|
|
||||||
|
const InlineKeyboardAttachment({
|
||||||
|
this.callbackId,
|
||||||
|
required this.rows,
|
||||||
|
}) : super(type: AttachmentType.inlineKeyboard);
|
||||||
|
|
||||||
|
bool get isEmpty => rows.every((row) => row.isEmpty);
|
||||||
|
|
||||||
|
factory InlineKeyboardAttachment.fromMap(Map<String, dynamic> map) {
|
||||||
|
final keyboard = map['keyboard'];
|
||||||
|
final rawRows = keyboard is Map ? keyboard['buttons'] as List? : null;
|
||||||
|
final rows = <List<InlineKeyboardButton>>[];
|
||||||
|
if (rawRows != null) {
|
||||||
|
for (final row in rawRows) {
|
||||||
|
if (row is! List) continue;
|
||||||
|
rows.add(
|
||||||
|
row
|
||||||
|
.whereType<Map>()
|
||||||
|
.map(
|
||||||
|
(b) =>
|
||||||
|
InlineKeyboardButton.fromMap(Map<String, dynamic>.from(b)),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return InlineKeyboardAttachment(
|
||||||
|
callbackId: map['callbackId']?.toString(),
|
||||||
|
rows: rows,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toMap() => {
|
||||||
|
'_type': 'INLINE_KEYBOARD',
|
||||||
|
if (callbackId != null) 'callbackId': callbackId,
|
||||||
|
'keyboard': {
|
||||||
|
'buttons': rows
|
||||||
|
.map((row) => row.map((b) => b.toMap()).toList())
|
||||||
|
.toList(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class ForwardedMessageAttachment extends MessageAttachment {
|
class ForwardedMessageAttachment extends MessageAttachment {
|
||||||
final int originalSenderId;
|
final int originalSenderId;
|
||||||
final String? originalSenderName;
|
final String? originalSenderName;
|
||||||
|
|||||||
Reference in New Issue
Block a user