🐛 Fixes of videos and more
This commit is contained in:
@@ -89,6 +89,13 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<!-- Livekit Screenshare -->
|
||||||
|
<service
|
||||||
|
android:name="de.julianassmann.flutter_background.IsolateHolderService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false"
|
||||||
|
android:foregroundServiceType="mediaProjection" />
|
||||||
|
|
||||||
<!-- Sign in with Apple -->
|
<!-- Sign in with Apple -->
|
||||||
<activity
|
<activity
|
||||||
android:name="com.aboutyou.dart_packages.sign_in_with_apple.SignInWithAppleCallback"
|
android:name="com.aboutyou.dart_packages.sign_in_with_apple.SignInWithAppleCallback"
|
||||||
|
@@ -3,13 +3,15 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 54;
|
objectVersion = 77;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
73ACDFAD2E3D0E6100B63535 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */; };
|
||||||
|
73ACDFC32E3D0E6100B63535 /* SolianBroadcastExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
73CDD6812DEC00480059D95D /* SolianNotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
73CDD6812DEC00480059D95D /* SolianNotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
73D4264B2DEB815D006C0AAE /* NotifyDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73D4264A2DEB815D006C0AAE /* NotifyDelegate.swift */; };
|
73D4264B2DEB815D006C0AAE /* NotifyDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73D4264A2DEB815D006C0AAE /* NotifyDelegate.swift */; };
|
||||||
@@ -32,6 +34,13 @@
|
|||||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||||
remoteInfo = Runner;
|
remoteInfo = Runner;
|
||||||
};
|
};
|
||||||
|
73ACDFC12E3D0E6100B63535 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 73ACDFAA2E3D0E6100B63535;
|
||||||
|
remoteInfo = SolianBroadcastExtension;
|
||||||
|
};
|
||||||
73C305D62E0BE878009035B9 /* PBXContainerItemProxy */ = {
|
73C305D62E0BE878009035B9 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
@@ -55,6 +64,7 @@
|
|||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
|
73ACDFC32E3D0E6100B63535 /* SolianBroadcastExtension.appex in Embed Foundation Extensions */,
|
||||||
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */,
|
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */,
|
||||||
73CDD6812DEC00480059D95D /* SolianNotificationService.appex in Embed Foundation Extensions */,
|
73CDD6812DEC00480059D95D /* SolianNotificationService.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
@@ -91,6 +101,9 @@
|
|||||||
3A1C47BD29CC6AC2587D4DBE /* 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 = "<group>"; };
|
3A1C47BD29CC6AC2587D4DBE /* 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 = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
|
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
|
||||||
|
73ACDFB82E3D0E6100B63535 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||||
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianNotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianNotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
73D4264A2DEB815D006C0AAE /* NotifyDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyDelegate.swift; sourceTree = "<group>"; };
|
73D4264A2DEB815D006C0AAE /* NotifyDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyDelegate.swift; sourceTree = "<group>"; };
|
||||||
@@ -117,6 +130,13 @@
|
|||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
73ACDFCA2E3D0E6100B63535 /* Exceptions for "SolianBroadcastExtension" folder in "SolianBroadcastExtension" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */;
|
||||||
|
};
|
||||||
73C305DC2E0BE878009035B9 /* Exceptions for "SolianShareExtension" folder in "SolianShareExtension" target */ = {
|
73C305DC2E0BE878009035B9 /* Exceptions for "SolianShareExtension" folder in "SolianShareExtension" target */ = {
|
||||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
membershipExceptions = (
|
membershipExceptions = (
|
||||||
@@ -150,6 +170,14 @@
|
|||||||
path = Services;
|
path = Services;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
73ACDFAE2E3D0E6100B63535 /* SolianBroadcastExtension */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
73ACDFCA2E3D0E6100B63535 /* Exceptions for "SolianBroadcastExtension" folder in "SolianBroadcastExtension" target */,
|
||||||
|
);
|
||||||
|
path = SolianBroadcastExtension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
73C305CF2E0BE878009035B9 /* SolianShareExtension */ = {
|
73C305CF2E0BE878009035B9 /* SolianShareExtension */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
exceptions = (
|
exceptions = (
|
||||||
@@ -177,6 +205,14 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
73ACDFA82E3D0E6100B63535 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
73ACDFAD2E3D0E6100B63535 /* ReplayKit.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
73C305CB2E0BE878009035B9 /* Frameworks */ = {
|
73C305CB2E0BE878009035B9 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -220,6 +256,8 @@
|
|||||||
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */,
|
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */,
|
||||||
39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */,
|
39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */,
|
||||||
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */,
|
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */,
|
||||||
|
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */,
|
||||||
|
73ACDFB82E3D0E6100B63535 /* UIKit.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -264,6 +302,7 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
||||||
73C305CF2E0BE878009035B9 /* SolianShareExtension */,
|
73C305CF2E0BE878009035B9 /* SolianShareExtension */,
|
||||||
|
73ACDFAE2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
91E124CE95BCB4DCD890160D /* Pods */,
|
91E124CE95BCB4DCD890160D /* Pods */,
|
||||||
@@ -279,6 +318,7 @@
|
|||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||||
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */,
|
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */,
|
||||||
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */,
|
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */,
|
||||||
|
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -323,6 +363,28 @@
|
|||||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.unit-test";
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
};
|
};
|
||||||
|
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */;
|
||||||
|
buildPhases = (
|
||||||
|
73ACDFA72E3D0E6100B63535 /* Sources */,
|
||||||
|
73ACDFA82E3D0E6100B63535 /* Frameworks */,
|
||||||
|
73ACDFA92E3D0E6100B63535 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
73ACDFAE2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||||
|
);
|
||||||
|
name = SolianBroadcastExtension;
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = SolianBroadcastExtension;
|
||||||
|
productReference = 73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
73C305CD2E0BE878009035B9 /* SolianShareExtension */ = {
|
73C305CD2E0BE878009035B9 /* SolianShareExtension */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 73C305DD2E0BE878009035B9 /* Build configuration list for PBXNativeTarget "SolianShareExtension" */;
|
buildConfigurationList = 73C305DD2E0BE878009035B9 /* Build configuration list for PBXNativeTarget "SolianShareExtension" */;
|
||||||
@@ -385,6 +447,7 @@
|
|||||||
dependencies = (
|
dependencies = (
|
||||||
73CDD6802DEC00480059D95D /* PBXTargetDependency */,
|
73CDD6802DEC00480059D95D /* PBXTargetDependency */,
|
||||||
73C305D72E0BE878009035B9 /* PBXTargetDependency */,
|
73C305D72E0BE878009035B9 /* PBXTargetDependency */,
|
||||||
|
73ACDFC22E3D0E6100B63535 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
73268D272DEB012A0076E970 /* Services */,
|
73268D272DEB012A0076E970 /* Services */,
|
||||||
@@ -409,6 +472,9 @@
|
|||||||
CreatedOnToolsVersion = 14.0;
|
CreatedOnToolsVersion = 14.0;
|
||||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||||
};
|
};
|
||||||
|
73ACDFAA2E3D0E6100B63535 = {
|
||||||
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
};
|
||||||
73C305CD2E0BE878009035B9 = {
|
73C305CD2E0BE878009035B9 = {
|
||||||
CreatedOnToolsVersion = 16.4;
|
CreatedOnToolsVersion = 16.4;
|
||||||
};
|
};
|
||||||
@@ -438,6 +504,7 @@
|
|||||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||||
73CDD6792DEC00480059D95D /* SolianNotificationService */,
|
73CDD6792DEC00480059D95D /* SolianNotificationService */,
|
||||||
73C305CD2E0BE878009035B9 /* SolianShareExtension */,
|
73C305CD2E0BE878009035B9 /* SolianShareExtension */,
|
||||||
|
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -450,6 +517,13 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
73ACDFA92E3D0E6100B63535 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
73C305CC2E0BE878009035B9 /* Resources */ = {
|
73C305CC2E0BE878009035B9 /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -525,10 +599,14 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
@@ -586,10 +664,14 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
@@ -643,6 +725,13 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
73ACDFA72E3D0E6100B63535 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
73C305CA2E0BE878009035B9 /* Sources */ = {
|
73C305CA2E0BE878009035B9 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -675,6 +764,11 @@
|
|||||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
73ACDFC22E3D0E6100B63535 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */;
|
||||||
|
targetProxy = 73ACDFC12E3D0E6100B63535 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
73C305D72E0BE878009035B9 /* PBXTargetDependency */ = {
|
73C305D72E0BE878009035B9 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = 73C305CD2E0BE878009035B9 /* SolianShareExtension */;
|
target = 73C305CD2E0BE878009035B9 /* SolianShareExtension */;
|
||||||
@@ -773,7 +867,7 @@
|
|||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -836,6 +930,123 @@
|
|||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
73ACDFC42E3D0E6100B63535 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = SolianBroadcastExtension/SolianBroadcastExtension.entitlements;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = SolianBroadcastExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = SolianBroadcastExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianBroadcastExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
73ACDFC52E3D0E6100B63535 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = SolianBroadcastExtension/SolianBroadcastExtension.entitlements;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = SolianBroadcastExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = SolianBroadcastExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianBroadcastExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
73ACDFC62E3D0E6100B63535 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = SolianBroadcastExtension/SolianBroadcastExtension.entitlements;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = SolianBroadcastExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = SolianBroadcastExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianBroadcastExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
73C305D92E0BE878009035B9 /* Debug */ = {
|
73C305D92E0BE878009035B9 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 17FAB080A9C53193ABD9C15B /* Pods-SolianShareExtension.debug.xcconfig */;
|
baseConfigurationReference = 17FAB080A9C53193ABD9C15B /* Pods-SolianShareExtension.debug.xcconfig */;
|
||||||
@@ -1204,7 +1415,7 @@
|
|||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1232,7 +1443,7 @@
|
|||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1258,6 +1469,16 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
73ACDFC42E3D0E6100B63535 /* Debug */,
|
||||||
|
73ACDFC52E3D0E6100B63535 /* Release */,
|
||||||
|
73ACDFC62E3D0E6100B63535 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
73C305DD2E0BE878009035B9 /* Build configuration list for PBXNativeTarget "SolianShareExtension" */ = {
|
73C305DD2E0BE878009035B9 /* Build configuration list for PBXNativeTarget "SolianShareExtension" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
37
ios/SolianBroadcastExtension/Atomic.swift
Normal file
37
ios/SolianBroadcastExtension/Atomic.swift
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Atomic.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Maksym Shcheglov.
|
||||||
|
// https://www.onswiftwings.com/posts/atomic-property-wrapper/
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct Atomic<Value> {
|
||||||
|
|
||||||
|
private var value: Value
|
||||||
|
private let lock = NSLock()
|
||||||
|
|
||||||
|
init(wrappedValue value: Value) {
|
||||||
|
self.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrappedValue: Value {
|
||||||
|
get { load() }
|
||||||
|
set { store(newValue: newValue) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func load() -> Value {
|
||||||
|
lock.lock()
|
||||||
|
defer { lock.unlock() }
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func store(newValue: Value) {
|
||||||
|
lock.lock()
|
||||||
|
defer { lock.unlock() }
|
||||||
|
value = newValue
|
||||||
|
}
|
||||||
|
}
|
29
ios/SolianBroadcastExtension/DarwinNotification.swift
Normal file
29
ios/SolianBroadcastExtension/DarwinNotification.swift
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// DarwinNotificationCenter.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 23/03/2021.
|
||||||
|
// Copyright © 2021 8x8, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum DarwinNotification: String {
|
||||||
|
case broadcastStarted = "iOS_BroadcastStarted"
|
||||||
|
case broadcastStopped = "iOS_BroadcastStopped"
|
||||||
|
}
|
||||||
|
|
||||||
|
class DarwinNotificationCenter {
|
||||||
|
|
||||||
|
static let shared = DarwinNotificationCenter()
|
||||||
|
|
||||||
|
private let notificationCenter: CFNotificationCenter
|
||||||
|
|
||||||
|
init() {
|
||||||
|
notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
func postNotification(_ name: DarwinNotification) {
|
||||||
|
CFNotificationCenterPostNotification(notificationCenter, CFNotificationName(rawValue: name.rawValue as CFString), nil, nil, true)
|
||||||
|
}
|
||||||
|
}
|
15
ios/SolianBroadcastExtension/Info.plist
Normal file
15
ios/SolianBroadcastExtension/Info.plist
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.broadcast-services-upload</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).SampleHandler</string>
|
||||||
|
<key>RPBroadcastProcessMode</key>
|
||||||
|
<string>RPBroadcastProcessModeSampleBuffer</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
103
ios/SolianBroadcastExtension/SampleHandler.swift
Normal file
103
ios/SolianBroadcastExtension/SampleHandler.swift
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
//
|
||||||
|
// SampleHandler.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 04.06.2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ReplayKit
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
let broadcastLogger = OSLog(subsystem: "dev.solsynth.solian", category: "Broadcast")
|
||||||
|
private enum Constants {
|
||||||
|
// the App Group ID value that the app and the broadcast extension targets are setup with. It differs for each app.
|
||||||
|
static let appGroupIdentifier = "group.solsynth.solian"
|
||||||
|
}
|
||||||
|
|
||||||
|
class SampleHandler: RPBroadcastSampleHandler {
|
||||||
|
|
||||||
|
private var clientConnection: SocketConnection?
|
||||||
|
private var uploader: SampleUploader?
|
||||||
|
|
||||||
|
private var frameCount: Int = 0
|
||||||
|
|
||||||
|
var socketFilePath: String {
|
||||||
|
let sharedContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupIdentifier)
|
||||||
|
return sharedContainer?.appendingPathComponent("rtc_SSFD").path ?? ""
|
||||||
|
}
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
if let connection = SocketConnection(filePath: socketFilePath) {
|
||||||
|
clientConnection = connection
|
||||||
|
setupConnection()
|
||||||
|
|
||||||
|
uploader = SampleUploader(connection: connection)
|
||||||
|
}
|
||||||
|
os_log(.debug, log: broadcastLogger, "%{public}s", socketFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastStarted(withSetupInfo setupInfo: [String: NSObject]?) {
|
||||||
|
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
|
||||||
|
frameCount = 0
|
||||||
|
|
||||||
|
DarwinNotificationCenter.shared.postNotification(.broadcastStarted)
|
||||||
|
openConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastPaused() {
|
||||||
|
// User has requested to pause the broadcast. Samples will stop being delivered.
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastResumed() {
|
||||||
|
// User has requested to resume the broadcast. Samples delivery will resume.
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastFinished() {
|
||||||
|
// User has requested to finish the broadcast.
|
||||||
|
DarwinNotificationCenter.shared.postNotification(.broadcastStopped)
|
||||||
|
clientConnection?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
|
||||||
|
switch sampleBufferType {
|
||||||
|
case RPSampleBufferType.video:
|
||||||
|
uploader?.send(sample: sampleBuffer)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SampleHandler {
|
||||||
|
|
||||||
|
func setupConnection() {
|
||||||
|
clientConnection?.didClose = { [weak self] error in
|
||||||
|
os_log(.debug, log: broadcastLogger, "client connection did close \(String(describing: error))")
|
||||||
|
|
||||||
|
if let error = error {
|
||||||
|
self?.finishBroadcastWithError(error)
|
||||||
|
} else {
|
||||||
|
// the displayed failure message is more user friendly when using NSError instead of Error
|
||||||
|
let JMScreenSharingStopped = 10001
|
||||||
|
let customError = NSError(domain: RPRecordingErrorDomain, code: JMScreenSharingStopped, userInfo: [NSLocalizedDescriptionKey: "Screen sharing stopped"])
|
||||||
|
self?.finishBroadcastWithError(customError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func openConnection() {
|
||||||
|
let queue = DispatchQueue(label: "broadcast.connectTimer")
|
||||||
|
let timer = DispatchSource.makeTimerSource(queue: queue)
|
||||||
|
timer.schedule(deadline: .now(), repeating: .milliseconds(100), leeway: .milliseconds(500))
|
||||||
|
timer.setEventHandler { [weak self] in
|
||||||
|
guard self?.clientConnection?.open() == true else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
timer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
timer.resume()
|
||||||
|
}
|
||||||
|
}
|
147
ios/SolianBroadcastExtension/SampleUploader.swift
Normal file
147
ios/SolianBroadcastExtension/SampleUploader.swift
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
//
|
||||||
|
// SampleUploader.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 22/03/2021.
|
||||||
|
// Copyright © 2021 8x8, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ReplayKit
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
private enum Constants {
|
||||||
|
static let bufferMaxLength = 10240
|
||||||
|
}
|
||||||
|
|
||||||
|
class SampleUploader {
|
||||||
|
|
||||||
|
private static var imageContext = CIContext(options: nil)
|
||||||
|
|
||||||
|
@Atomic private var isReady = false
|
||||||
|
private var connection: SocketConnection
|
||||||
|
|
||||||
|
private var dataToSend: Data?
|
||||||
|
private var byteIndex = 0
|
||||||
|
|
||||||
|
private let serialQueue: DispatchQueue
|
||||||
|
|
||||||
|
init(connection: SocketConnection) {
|
||||||
|
self.connection = connection
|
||||||
|
self.serialQueue = DispatchQueue(label: "org.jitsi.meet.broadcast.sampleUploader")
|
||||||
|
|
||||||
|
setupConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult func send(sample buffer: CMSampleBuffer) -> Bool {
|
||||||
|
guard isReady else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
isReady = false
|
||||||
|
|
||||||
|
dataToSend = prepare(sample: buffer)
|
||||||
|
byteIndex = 0
|
||||||
|
|
||||||
|
serialQueue.async { [weak self] in
|
||||||
|
self?.sendDataChunk()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SampleUploader {
|
||||||
|
|
||||||
|
func setupConnection() {
|
||||||
|
connection.didOpen = { [weak self] in
|
||||||
|
self?.isReady = true
|
||||||
|
}
|
||||||
|
connection.streamHasSpaceAvailable = { [weak self] in
|
||||||
|
self?.serialQueue.async {
|
||||||
|
if let success = self?.sendDataChunk() {
|
||||||
|
self?.isReady = !success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult func sendDataChunk() -> Bool {
|
||||||
|
guard let dataToSend = dataToSend else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytesLeft = dataToSend.count - byteIndex
|
||||||
|
var length = bytesLeft > Constants.bufferMaxLength ? Constants.bufferMaxLength : bytesLeft
|
||||||
|
|
||||||
|
length = dataToSend[byteIndex..<(byteIndex + length)].withUnsafeBytes {
|
||||||
|
guard let ptr = $0.bindMemory(to: UInt8.self).baseAddress else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection.writeToStream(buffer: ptr, maxLength: length)
|
||||||
|
}
|
||||||
|
|
||||||
|
if length > 0 {
|
||||||
|
byteIndex += length
|
||||||
|
bytesLeft -= length
|
||||||
|
|
||||||
|
if bytesLeft == 0 {
|
||||||
|
self.dataToSend = nil
|
||||||
|
byteIndex = 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "writeBufferToStream failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepare(sample buffer: CMSampleBuffer) -> Data? {
|
||||||
|
guard let imageBuffer = CMSampleBufferGetImageBuffer(buffer) else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "image buffer not available")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
CVPixelBufferLockBaseAddress(imageBuffer, .readOnly)
|
||||||
|
|
||||||
|
let scaleFactor = 1.0
|
||||||
|
let width = CVPixelBufferGetWidth(imageBuffer)/Int(scaleFactor)
|
||||||
|
let height = CVPixelBufferGetHeight(imageBuffer)/Int(scaleFactor)
|
||||||
|
let orientation = CMGetAttachment(buffer, key: RPVideoSampleOrientationKey as CFString, attachmentModeOut: nil)?.uintValue ?? 0
|
||||||
|
|
||||||
|
let scaleTransform = CGAffineTransform(scaleX: CGFloat(1.0/scaleFactor), y: CGFloat(1.0/scaleFactor))
|
||||||
|
let bufferData = self.jpegData(from: imageBuffer, scale: scaleTransform)
|
||||||
|
|
||||||
|
CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly)
|
||||||
|
|
||||||
|
guard let messageData = bufferData else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "corrupted image buffer")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let httpResponse = CFHTTPMessageCreateResponse(nil, 200, nil, kCFHTTPVersion1_1).takeRetainedValue()
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Content-Length" as CFString, String(messageData.count) as CFString)
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Width" as CFString, String(width) as CFString)
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Height" as CFString, String(height) as CFString)
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Orientation" as CFString, String(orientation) as CFString)
|
||||||
|
|
||||||
|
CFHTTPMessageSetBody(httpResponse, messageData as CFData)
|
||||||
|
|
||||||
|
let serializedMessage = CFHTTPMessageCopySerializedMessage(httpResponse)?.takeRetainedValue() as Data?
|
||||||
|
|
||||||
|
return serializedMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func jpegData(from buffer: CVPixelBuffer, scale scaleTransform: CGAffineTransform) -> Data? {
|
||||||
|
let image = CIImage(cvPixelBuffer: buffer).transformed(by: scaleTransform)
|
||||||
|
|
||||||
|
guard let colorSpace = image.colorSpace else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let options: [CIImageRepresentationOption: Float] = [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption: 1.0]
|
||||||
|
|
||||||
|
return SampleUploader.imageContext.jpegRepresentation(of: image, colorSpace: colorSpace, options: options)
|
||||||
|
}
|
||||||
|
}
|
199
ios/SolianBroadcastExtension/SocketConnection.swift
Normal file
199
ios/SolianBroadcastExtension/SocketConnection.swift
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
//
|
||||||
|
// SocketConnection.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 22/03/2021.
|
||||||
|
// Copyright © 2021 Atlassian Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
class SocketConnection: NSObject {
|
||||||
|
var didOpen: (() -> Void)?
|
||||||
|
var didClose: ((Error?) -> Void)?
|
||||||
|
var streamHasSpaceAvailable: (() -> Void)?
|
||||||
|
|
||||||
|
private let filePath: String
|
||||||
|
private var socketHandle: Int32 = -1
|
||||||
|
private var address: sockaddr_un?
|
||||||
|
|
||||||
|
private var inputStream: InputStream?
|
||||||
|
private var outputStream: OutputStream?
|
||||||
|
|
||||||
|
private var networkQueue: DispatchQueue?
|
||||||
|
private var shouldKeepRunning = false
|
||||||
|
|
||||||
|
init?(filePath path: String) {
|
||||||
|
filePath = path
|
||||||
|
socketHandle = Darwin.socket(AF_UNIX, SOCK_STREAM, 0)
|
||||||
|
|
||||||
|
guard socketHandle != -1 else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: create socket")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func open() -> Bool {
|
||||||
|
os_log(.debug, log: broadcastLogger, "open socket connection")
|
||||||
|
|
||||||
|
guard FileManager.default.fileExists(atPath: filePath) else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: socket file missing")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
guard setupAddress() == true else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
guard connectSocket() == true else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
setupStreams()
|
||||||
|
|
||||||
|
inputStream?.open()
|
||||||
|
outputStream?.open()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func close() {
|
||||||
|
unscheduleStreams()
|
||||||
|
|
||||||
|
inputStream?.delegate = nil
|
||||||
|
outputStream?.delegate = nil
|
||||||
|
|
||||||
|
inputStream?.close()
|
||||||
|
outputStream?.close()
|
||||||
|
|
||||||
|
inputStream = nil
|
||||||
|
outputStream = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeToStream(buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int {
|
||||||
|
outputStream?.write(buffer, maxLength: length) ?? 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SocketConnection: StreamDelegate {
|
||||||
|
|
||||||
|
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
|
||||||
|
switch eventCode {
|
||||||
|
case .openCompleted:
|
||||||
|
os_log(.debug, log: broadcastLogger, "client stream open completed")
|
||||||
|
if aStream == outputStream {
|
||||||
|
didOpen?()
|
||||||
|
}
|
||||||
|
case .hasBytesAvailable:
|
||||||
|
if aStream == inputStream {
|
||||||
|
var buffer: UInt8 = 0
|
||||||
|
let numberOfBytesRead = inputStream?.read(&buffer, maxLength: 1)
|
||||||
|
if numberOfBytesRead == 0 && aStream.streamStatus == .atEnd {
|
||||||
|
os_log(.debug, log: broadcastLogger, "server socket closed")
|
||||||
|
close()
|
||||||
|
notifyDidClose(error: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .hasSpaceAvailable:
|
||||||
|
if aStream == outputStream {
|
||||||
|
streamHasSpaceAvailable?()
|
||||||
|
}
|
||||||
|
case .errorOccurred:
|
||||||
|
os_log(.debug, log: broadcastLogger, "client stream error occured: \(String(describing: aStream.streamError))")
|
||||||
|
close()
|
||||||
|
notifyDidClose(error: aStream.streamError)
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SocketConnection {
|
||||||
|
|
||||||
|
func setupAddress() -> Bool {
|
||||||
|
var addr = sockaddr_un()
|
||||||
|
guard filePath.count < MemoryLayout.size(ofValue: addr.sun_path) else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: fd path is too long")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = withUnsafeMutablePointer(to: &addr.sun_path.0) { ptr in
|
||||||
|
filePath.withCString {
|
||||||
|
strncpy(ptr, $0, filePath.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address = addr
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectSocket() -> Bool {
|
||||||
|
guard var addr = address else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = withUnsafePointer(to: &addr) { ptr in
|
||||||
|
ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) {
|
||||||
|
Darwin.connect(socketHandle, $0, socklen_t(MemoryLayout<sockaddr_un>.size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guard status == noErr else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: \(status)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupStreams() {
|
||||||
|
var readStream: Unmanaged<CFReadStream>?
|
||||||
|
var writeStream: Unmanaged<CFWriteStream>?
|
||||||
|
|
||||||
|
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketHandle, &readStream, &writeStream)
|
||||||
|
|
||||||
|
inputStream = readStream?.takeRetainedValue()
|
||||||
|
inputStream?.delegate = self
|
||||||
|
inputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
|
||||||
|
|
||||||
|
outputStream = writeStream?.takeRetainedValue()
|
||||||
|
outputStream?.delegate = self
|
||||||
|
outputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
|
||||||
|
|
||||||
|
scheduleStreams()
|
||||||
|
}
|
||||||
|
|
||||||
|
func scheduleStreams() {
|
||||||
|
shouldKeepRunning = true
|
||||||
|
|
||||||
|
networkQueue = DispatchQueue.global(qos: .userInitiated)
|
||||||
|
networkQueue?.async { [weak self] in
|
||||||
|
self?.inputStream?.schedule(in: .current, forMode: .common)
|
||||||
|
self?.outputStream?.schedule(in: .current, forMode: .common)
|
||||||
|
RunLoop.current.run()
|
||||||
|
|
||||||
|
var isRunning = false
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
isRunning = self?.shouldKeepRunning ?? false && RunLoop.current.run(mode: .default, before: .distantFuture)
|
||||||
|
} while (isRunning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unscheduleStreams() {
|
||||||
|
networkQueue?.sync { [weak self] in
|
||||||
|
self?.inputStream?.remove(from: .current, forMode: .common)
|
||||||
|
self?.outputStream?.remove(from: .current, forMode: .common)
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldKeepRunning = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyDidClose(error: Error?) {
|
||||||
|
if didClose != nil {
|
||||||
|
didClose?(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.solsynth.solian</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:developer';
|
||||||
import 'package:island/widgets/chat/call_button.dart';
|
import 'package:island/widgets/chat/call_button.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
@@ -203,7 +204,13 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
|
|
||||||
Future<void> joinRoom(String roomId) async {
|
Future<void> joinRoom(String roomId) async {
|
||||||
if (_roomId == roomId && _room != null) {
|
if (_roomId == roomId && _room != null) {
|
||||||
|
log('[Call] Call skipped. Already has data');
|
||||||
return;
|
return;
|
||||||
|
} else if (_room != null) {
|
||||||
|
if (!_room!.isDisposed &&
|
||||||
|
_room!.connectionState != ConnectionState.disconnected) {
|
||||||
|
throw Exception('Call already connected');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_roomId = roomId;
|
_roomId = roomId;
|
||||||
if (_room != null) {
|
if (_room != null) {
|
||||||
@@ -335,5 +342,6 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
_room?.removeListener(_onRoomChange);
|
_room?.removeListener(_onRoomChange);
|
||||||
_room?.dispose();
|
_room?.dispose();
|
||||||
_durationTimer?.cancel();
|
_durationTimer?.cancel();
|
||||||
|
_roomId = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
@@ -8,6 +10,7 @@ import 'package:island/widgets/app_scaffold.dart';
|
|||||||
import 'package:island/widgets/chat/call_button.dart';
|
import 'package:island/widgets/chat/call_button.dart';
|
||||||
import 'package:island/widgets/chat/call_overlay.dart';
|
import 'package:island/widgets/chat/call_overlay.dart';
|
||||||
import 'package:island/widgets/chat/call_participant_tile.dart';
|
import 'package:island/widgets/chat/call_participant_tile.dart';
|
||||||
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
@@ -23,7 +26,19 @@ class CallScreen extends HookConsumerWidget {
|
|||||||
final callNotifier = ref.watch(callNotifierProvider.notifier);
|
final callNotifier = ref.watch(callNotifierProvider.notifier);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
|
log('[Call] Joining the call...');
|
||||||
|
callNotifier.joinRoom(roomId).catchError((_) {
|
||||||
|
showConfirmAlert(
|
||||||
|
'Seems there already has a call connected, do you want override it?',
|
||||||
|
'Call already connected',
|
||||||
|
).then((value) {
|
||||||
|
if (value != true) return;
|
||||||
|
log('[Call] Joining the call... with overrides');
|
||||||
|
callNotifier.disconnect();
|
||||||
|
callNotifier.dispose();
|
||||||
callNotifier.joinRoom(roomId);
|
callNotifier.joinRoom(roomId);
|
||||||
|
});
|
||||||
|
});
|
||||||
return null;
|
return null;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@@ -63,12 +63,7 @@ class CallControlsBar extends HookConsumerWidget {
|
|||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
builder:
|
builder:
|
||||||
(context) => ClipRRect(
|
(innerContext) => Column(
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(8),
|
|
||||||
topRight: Radius.circular(8),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -76,7 +71,8 @@ class CallControlsBar extends HookConsumerWidget {
|
|||||||
title: Text('callLeave').tr(),
|
title: Text('callLeave').tr(),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
callNotifier.disconnect();
|
callNotifier.disconnect();
|
||||||
GoRouter.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(innerContext).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -86,12 +82,20 @@ class CallControlsBar extends HookConsumerWidget {
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
callNotifier.disconnect();
|
callNotifier.disconnect();
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
try {
|
||||||
|
showLoadingModal(context);
|
||||||
await apiClient.delete(
|
await apiClient.delete(
|
||||||
'/sphere/chat/realtime/${callNotifier.roomId}',
|
'/sphere/chat/realtime/${callNotifier.roomId}',
|
||||||
);
|
);
|
||||||
callNotifier.dispose();
|
callNotifier.dispose();
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
GoRouter.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(innerContext).pop();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) hideLoadingModal(context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -99,7 +103,6 @@ class CallControlsBar extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
backgroundColor: const Color(0xFFE53E3E),
|
backgroundColor: const Color(0xFFE53E3E),
|
||||||
iconColor: Colors.white,
|
iconColor: Colors.white,
|
||||||
),
|
),
|
||||||
|
@@ -4,10 +4,12 @@ import 'package:flutter/material.dart';
|
|||||||
class UniversalVideo extends StatelessWidget {
|
class UniversalVideo extends StatelessWidget {
|
||||||
final String uri;
|
final String uri;
|
||||||
final double aspectRatio;
|
final double aspectRatio;
|
||||||
|
final bool autoplay;
|
||||||
const UniversalVideo({
|
const UniversalVideo({
|
||||||
super.key,
|
super.key,
|
||||||
required this.uri,
|
required this.uri,
|
||||||
required this.aspectRatio,
|
required this.aspectRatio,
|
||||||
|
this.autoplay = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@@ -573,10 +573,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: file_picker
|
name: file_picker
|
||||||
sha256: ef9908739bdd9c476353d6adff72e88fd00c625f5b959ae23f7567bd5137db0a
|
sha256: "13ba4e627ef24503a465d1d61b32596ce10eb6b8903678d362a528f9939b4aa8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.2.0"
|
version: "10.2.1"
|
||||||
file_selector_linux:
|
file_selector_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1097,10 +1097,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: google_fonts
|
name: google_fonts
|
||||||
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
|
sha256: df9763500dadba0155373e9cb44e202ce21bd9ed5de6bdbd05c5854e86839cb8
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.1"
|
version: "6.3.0"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@@ -53,7 +53,7 @@ dependencies:
|
|||||||
flutter_highlight: ^0.7.0
|
flutter_highlight: ^0.7.0
|
||||||
uuid: ^4.5.1
|
uuid: ^4.5.1
|
||||||
url_launcher: ^6.3.2
|
url_launcher: ^6.3.2
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.3.0
|
||||||
gap: ^3.0.1
|
gap: ^3.0.1
|
||||||
cached_network_image: ^3.4.1
|
cached_network_image: ^3.4.1
|
||||||
web: ^1.1.1
|
web: ^1.1.1
|
||||||
@@ -73,7 +73,7 @@ dependencies:
|
|||||||
git: https://github.com/LittleSheep2Code/tus_client.git
|
git: https://github.com/LittleSheep2Code/tus_client.git
|
||||||
cross_file: ^0.3.4+2
|
cross_file: ^0.3.4+2
|
||||||
image_picker: ^1.1.2
|
image_picker: ^1.1.2
|
||||||
file_picker: ^10.2.0
|
file_picker: ^10.2.1
|
||||||
riverpod_annotation: ^2.6.1
|
riverpod_annotation: ^2.6.1
|
||||||
image_picker_platform_interface: ^2.10.1
|
image_picker_platform_interface: ^2.10.1
|
||||||
image_picker_android: ^0.8.12+24
|
image_picker_android: ^0.8.12+24
|
||||||
|
Reference in New Issue
Block a user