157 lines
5.9 KiB
C++
157 lines
5.9 KiB
C++
#include "pch.h"
|
|
#include "ReactCameraViewManager.h"
|
|
#include "ReactCameraConstants.h"
|
|
|
|
#include <iomanip>
|
|
|
|
namespace winrt {
|
|
using namespace Windows::UI::Xaml;
|
|
using namespace Windows::UI::Xaml::Media;
|
|
using namespace Windows::UI::Xaml::Controls;
|
|
using namespace Windows::Devices::Enumeration;
|
|
using namespace Windows::Foundation;
|
|
using namespace Windows::Foundation::Collections;
|
|
using namespace Windows::Media::MediaProperties;
|
|
using namespace Windows::Storage;
|
|
using namespace Windows::Storage::Streams;
|
|
using namespace Microsoft::ReactNative;
|
|
} //namespace winrt
|
|
|
|
|
|
namespace winrt::ReactNativeCameraCPP::implementation {
|
|
// static vector to contain all currently active camera view instances
|
|
// This is a temporary workaround to map the view tag to view instance, since
|
|
// Method call from ReactCameraModule constains view tag as parameter and we need
|
|
// to forward the call to CameraView instance.
|
|
std::vector<winrt::com_ptr<ReactNativeCameraCPP::ReactCameraView>> ReactCameraViewManager::m_cameraViewInstances;
|
|
|
|
ReactCameraViewManager::ReactCameraViewManager() {}
|
|
|
|
// IViewManager
|
|
hstring ReactCameraViewManager::Name() noexcept {
|
|
return L"RNCamera";
|
|
}
|
|
|
|
FrameworkElement ReactCameraViewManager::CreateView() noexcept {
|
|
auto const& view = ReactNativeCameraCPP::ReactCameraView::Create();
|
|
view->SetContext(m_reactContext);
|
|
m_cameraViewInstances.emplace_back(view);
|
|
|
|
return view.as<winrt::Grid>();
|
|
}
|
|
|
|
// IViewManagerWithReactContext
|
|
IReactContext ReactCameraViewManager::ReactContext() noexcept {
|
|
return m_reactContext;
|
|
}
|
|
|
|
void ReactCameraViewManager::ReactContext(IReactContext reactContext) noexcept {
|
|
m_reactContext = reactContext;
|
|
}
|
|
|
|
// IViewManagerWithNativeProperties
|
|
IMapView<hstring, ViewManagerPropertyType> ReactCameraViewManager::NativeProps() noexcept {
|
|
auto nativeProps = winrt::single_threaded_map<hstring, ViewManagerPropertyType>();
|
|
|
|
nativeProps.Insert(L"aspect", ViewManagerPropertyType::Number);
|
|
nativeProps.Insert(L"type", ViewManagerPropertyType::Number);
|
|
nativeProps.Insert(L"autoFocus", ViewManagerPropertyType::Boolean);
|
|
nativeProps.Insert(L"whiteBalance", ViewManagerPropertyType::Number);
|
|
nativeProps.Insert(L"torchMode", ViewManagerPropertyType::Number);
|
|
nativeProps.Insert(L"flashMode", ViewManagerPropertyType::Number);
|
|
// nativeProps.Insert(L"barcodeScannerEnabled", ViewManagerPropertyType::Boolean);
|
|
// nativeProps.Insert(L"barCodeTypes", ViewManagerPropertyType::Array);
|
|
nativeProps.Insert(L"keepAwake", ViewManagerPropertyType::Boolean);
|
|
|
|
return nativeProps.GetView();
|
|
}
|
|
|
|
void ReactCameraViewManager::UpdateProperties(
|
|
FrameworkElement const& view,
|
|
IJSValueReader const& propertyMapReader) noexcept {
|
|
if (auto reactCameraView = view.try_as<ReactNativeCameraCPP::ReactCameraView>()) {
|
|
reactCameraView->UpdateProperties(propertyMapReader);
|
|
}
|
|
}
|
|
|
|
void ReactCameraViewManager::RemoveViewFromList(winrt::com_ptr<ReactNativeCameraCPP::ReactCameraView> view)
|
|
{
|
|
auto it = std::find(m_cameraViewInstances.begin(), m_cameraViewInstances.end(), view);
|
|
if (it != m_cameraViewInstances.end())
|
|
m_cameraViewInstances.erase(it);
|
|
}
|
|
|
|
IAsyncAction ReactCameraViewManager::TakePictureAsync(
|
|
std::map<std::wstring, winrt::Microsoft::ReactNative::JSValue> const& options,
|
|
int viewTag,
|
|
ReactPromise<JSValueObject>& result)
|
|
{
|
|
auto index = co_await FindCamera(viewTag);
|
|
if (index != -1)
|
|
{
|
|
auto cameraView = m_cameraViewInstances.at(index);
|
|
co_await cameraView->TakePictureAsync(options, result);
|
|
}
|
|
else
|
|
{
|
|
result.Reject("No camera instance found.");
|
|
}
|
|
}
|
|
|
|
IAsyncAction ReactCameraViewManager::RecordAsync(
|
|
std::map<std::wstring, JSValue> const& options,
|
|
int viewTag,
|
|
ReactPromise<JSValueObject>& result)
|
|
{
|
|
auto index = co_await FindCamera(viewTag);
|
|
if (index != -1)
|
|
{
|
|
auto cameraView = m_cameraViewInstances.at(index);
|
|
co_await cameraView->RecordAsync(options, result);
|
|
}
|
|
else
|
|
{
|
|
result.Reject("No camera instance found.");
|
|
}
|
|
}
|
|
|
|
// Intialize MediaCapture and will bring up the constent dialog if this
|
|
// is the first time. RNC will display a progress indicator while waiting
|
|
// for user click. This method will resolve as no permission if user does
|
|
// not grant the permission or App does not have the appx capabilities for
|
|
// Microphone and WebCam specified in its Package.Appxmanifest.
|
|
IAsyncAction ReactCameraViewManager::CheckMediaCapturePermissionAsync(
|
|
winrt::Microsoft::ReactNative::ReactPromise<bool>& result)
|
|
{
|
|
auto mediaCapture = winrt::Windows::Media::Capture::MediaCapture();
|
|
bool hasPermission = true;
|
|
try {
|
|
co_await mediaCapture.InitializeAsync();
|
|
}
|
|
catch (winrt::hresult_error const&) {
|
|
hasPermission = false;
|
|
}
|
|
result.Resolve(hasPermission);
|
|
}
|
|
|
|
IAsyncOperation<int> ReactCameraViewManager::FindCamera(int viewTag)
|
|
{
|
|
int index = 0;
|
|
for (const auto& cameraView : m_cameraViewInstances)
|
|
{
|
|
auto element = cameraView.as<winrt::Grid>();
|
|
auto dispatcher = element.Dispatcher();
|
|
co_await resume_foreground(dispatcher);
|
|
int currentTag = static_cast<int>(element.GetValue(winrt::FrameworkElement::TagProperty()).as<winrt::IPropertyValue>().GetInt64());
|
|
if (currentTag == viewTag)
|
|
{
|
|
co_return index;
|
|
}
|
|
co_await resume_background();
|
|
index++;
|
|
}
|
|
co_return -1;
|
|
}
|
|
|
|
} // namespace winrt::ReactNativeCameraCPP::implementation
|